c# - OnPropertyChanged 不会与标签文本一起触发
问题描述
我在一个 Xamarin 应用程序中,我必须制作一个待办事项列表。我正在使用列表视图。每次添加新的待办事项时,我都必须动态设置标签文本:任务数 2/4,其中 2 是已完成的任务,4 是总任务。一切正常,但是当我必须更新标签文本时发现了一些问题。我正在使用 MVVM 模式。在 XAML 中,我将文本值绑定到 SetInfoDoneText。在 MainPage 中,我将 bindigContext 设置为 VM(TodoListViewModel)。我将 INotifyPropertyChanged 与 OnPropertyChanged 一起使用。我做了一个改变 setInfoDoneText 值的方法。问题是 set 和 get 仅被调用一次,并且当 setInfoDoneText 由 OnPropertyChanged 方法更新时不会再次触发。这是代码。问题是当我尝试更新 lblDoneInfo text () class 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>
解决方案
PropertyChanged
仅在您设置公共属性 的值时触发SetInfoDoneText
。您的代码正在设置字段的值setInfoDoneText
(小写)。
通常最好的做法是使字段private
防止这种情况发生
private String setInfoDoneText;
推荐阅读
- r - MatchIt 与多个单元
- jquery - 如何跳出Jquery进行迭代
- vb.net - 如何在 Visual Studio (VB) 中仅将 Word 段落的一部分加粗
- html - 行数据的 Html 表格设计问题
- mule - 如何处理 http 连接器响应代码
- javascript - React Semantic UI:Table.Header Cell 未占用全宽
- tensorflow - 将 InMemoryEvaluatorHook 与 TPU 一起使用会引发异常
- azure - Azure JWT 令牌密钥轮换
- android - 当视图变大时,我如何正确地在constraintLayout(android)中使用相邻的2条链而不覆盖链?
- javascript - D3.js:在没有 d3.drag 的情况下获得平移平移而无需缩放