首页 > 解决方案 > 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>

标签: c#xamarinmvvmbinding

解决方案


PropertyChanged仅在您设置公共属性 的值时触发SetInfoDoneText。您的代码正在设置字段的值setInfoDoneText(小写)。

通常最好的做法是使字段private防止这种情况发生

private String setInfoDoneText;

推荐阅读