【问题标题】:OnPropertyChanged not fire with label textOnPropertyChanged 不会与标签文本一起触发
【发布时间】: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>

【问题讨论】:

    标签: c# xamarin mvvm binding


    【解决方案1】:

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

    通常最好的做法是设置字段private 来防止这种情况

    private String setInfoDoneText;
    

    【讨论】:

    • 非常感谢您的帮助!但是我尝试用大写 S 更改 setInfoDoneText,现在应用程序运行但立即关闭...不知道为什么...我认为这属于无限循环或类似的东西。
    • 您只需要在UpdateDoneInfo 和VM 构造函数中更改它。如果您在属性设置器中更改它,您将创建一个无限循环,导致应用程序崩溃
    • 这就是重点!!!非常感谢您的宝贵时间!来自西班牙的最美好的祝愿!
    • 如果您不介意回答,还有一个问题!我如何将列表视图中的 checkbos 绑定到视图模型中的命令。我想要实现的是更改与以前相同的标签,但现在根据列表视图中检查的待办事项。问题是,如果我尝试在 listview 中正常绑定到 viewmodel,它不会触发命令功能。
    • 请使用相关代码发布一个新问题
    猜你喜欢
    • 1970-01-01
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 2016-09-08
    相关资源
    最近更新 更多