OnPropertyChanged 不会与标签文本一起触发
Posted
技术标签:
【中文标题】OnPropertyChanged 不会与标签文本一起触发【英文标题】:OnPropertyChanged not fire with label text 【发布时间】:2021-12-11 13:46:20 【问题描述】:我在一个 Xamarin 应用程序中,我必须制作一个待办事项列表。我正在使用列表视图。每次添加新的待办事项时,我都必须动态设置标签文本,如下所示:任务数 2/4,其中 2 是已完成的任务,4 是总任务。一切正常,但是当我必须更新标签文本时发现了一些问题。我正在使用 MVVM 模式。在 XAML 中,我将文本值绑定到 SetInfoDoneText。在 MainPage 中,我将 bindigContext 设置为 VM(TodoListViewModel)。我将 INotifyPropertyChanged 与 OnPropertyChanged 一起使用。我做了一个改变 setInfoDoneText 值的方法。问题是 set 和 get 仅被调用一次,并且当 setInfoDoneText 由 OnPropertyChanged 方法更新时不会再次触发。这是代码。 问题是当我尝试更新 lblDoneInfo 文本( ) 类 TodoListViewModel: INotifyPropertyChanged
public ObservableCollection<TodoItem> todoItems get; set;
public event PropertyChangedEventHandler PropertyChanged;
public String setInfoDoneText;
public String SetInfoDoneText
get => setInfoDoneText;
set
setInfoDoneText = value;
OnPropertyChanged("SetInfoDoneText");
protected void OnPropertyChanged(string propertyName = null)
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
int doneTask = 0;
int totalTask = 0;
public TodoListViewModel()
this.todoItems = new ObservableCollection<TodoItem>();
setInfoDoneText = "Number of tasks: " + doneTask + "/" + totalTask;
public ICommand AddTodoCommand => new Command(AddTodoItem);
public String newTodoInputValue get; set;
public String selectedItem get; set;
public bool highPriority get; set;
public bool midPriority get; set;
public bool lowPriority get; set;
Color newColor = new Color();
public void AddTodoItem()
if (highPriority)
newColor = Color.Red;
AddNewItem(newColor);
highPriority = false;
if (midPriority)
newColor = Color.Orange;
AddNewItem(newColor);
midPriority = false;
if (lowPriority)
newColor = Color.Yellow;
AddNewItem(newColor);
lowPriority = false;
public TodoItem AddNewItem(Color newColor)
TodoItem newItem = new TodoItem(newTodoInputValue,
false,
highPriority,
midPriority,
lowPriority,
newColor);
todoItems.Add(newItem);
UpdateDoneInfo();
return newItem;
public ICommand RemoveTodoCommand => new Command(RemoveTodoItem);
public void RemoveTodoItem(object o)
TodoItem todoItemBeingRemoved = o as TodoItem;
todoItems.Remove(todoItemBeingRemoved);
public ICommand EditTodoCommand => new Command(EditTodoItem);
public void EditTodoItem(object o)
TodoItem todoItemBeingEdited = o as TodoItem;
int newIndex = todoItems.IndexOf(todoItemBeingEdited);
todoItems.Remove(todoItemBeingEdited);
TodoItem updatedTodo = AddNewItem(newColor);
//todoItems.Add(updatedTodo);
int oldIndex = todoItems.IndexOf(updatedTodo);
todoItems.Move(oldIndex, newIndex);
public String UpdateDoneInfo()
totalTask = todoItems.Count;
foreach (TodoItem item in todoItems)
if (item.complete) doneTask++;
return setInfoDoneText = "Number of tasks: " + doneTask + "/" + totalTask;
<ContentPage.BindingContext>
<local:TodoListViewModel/>
</ContentPage.BindingContext>
<StackLayout>
<Entry
x:Name="inputField"
Text="Binding newTodoInputValue"
Placeholder="Enter a todo..."
/>
<Label x:Name="lblDoneInfo" Text="Binding SetInfoDoneText, Mode=TwoWay ">
</Label>
<FlexLayout AlignItems="Center" JustifyContent="SpaceBetween">
<input:CheckBox x:Name="highP"
IsChecked="Binding highPriority"
CheckChangedCommand="Binding AddTodoCommand"
Margin="0,0,20,0" />
<Label Text="High Priority" FontSize="Medium"/>
<input:CheckBox x:Name="midP"
IsChecked="Binding midPriority"
CheckChangedCommand="Binding AddTodoCommand"
Margin="0,0,20,0" />
<Label Text="Medium Priority" FontSize="Medium"/>
<input:CheckBox x:Name="lowP"
IsChecked="Binding lowPriority"
CheckChangedCommand="Binding AddTodoCommand"
Margin="0,0,20,0" />
<Label Text="Low Priority" FontSize="Medium"/>
</FlexLayout>
<ListView x:Name="todoList" ItemsSource="Binding todoItems" SelectedItem="Binding selectedItem">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="20">
<FlexLayout JustifyContent="SpaceBetween" AlignItems="Center" Padding="20,0">
<ContentView>
<FlexLayout AlignItems="Center">
<input:CheckBox IsChecked="Binding complete" Margin="5" />
<Label x:Name="todoText" TextColor="Binding color" Text="Binding todoText" FontSize="Large"/>
</FlexLayout>
</ContentView>
<ImageButton
Source="editar_24.png"
BackgroundColor="Transparent"
WidthRequest="100"
HeightRequest="100"
Margin="0,0,20,0"
Command="Binding Path=BindingContext.EditTodoCommand,
Source=x:Reference todoList"
CommandParameter="Binding ."/>
<ImageButton
Source="basura_24.png"
BackgroundColor="Transparent"
WidthRequest="100"
HeightRequest="100"
Command="Binding Path=BindingContext.RemoveTodoCommand,
Source=x:Reference todoList"
CommandParameter="Binding ."/>
</FlexLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
【问题讨论】:
【参考方案1】:PropertyChanged
仅在您设置 公共属性 SetInfoDoneText
的值时触发。您的代码正在设置字段 setInfoDoneText
(小写)的值。
通常最好的做法是设置字段private
来防止这种情况
private String setInfoDoneText;
【讨论】:
非常感谢您的帮助!但是我尝试用大写 S 更改 setInfoDoneText,现在应用程序运行但立即关闭...不知道为什么...我认为这属于无限循环或类似的东西。 您只需要在UpdateDoneInfo
和VM 构造函数中更改它。如果您在属性设置器中更改它,您将创建一个无限循环,导致应用程序崩溃
这就是重点!!!非常感谢您的宝贵时间!来自西班牙的最美好的祝愿!
如果您不介意回答,还有一个问题!我如何将列表视图中的 checkbos 绑定到视图模型中的命令。我想要实现的是更改与以前相同的标签,但现在根据列表视图中检查的待办事项。问题是,如果我尝试在 listview 中正常绑定到 viewmodel,它不会触发命令功能。
请使用相关代码发布一个新问题以上是关于OnPropertyChanged 不会与标签文本一起触发的主要内容,如果未能解决你的问题,请参考以下文章
WPF:多重绑定不使用 OnPropertyChanged 更新?
Xamarin Forms App Shell OnPropertyChanged 未更新 FlyoutHeader 视图
在不触发 OnPropertyChanged 的情况下更新 WPF DataGrid
OnPropertyChanged在WPF中的作用,越详细越好。谢谢了!!