简体   繁体   English

在ObservableCollection中更改模型属性时更新UI?

[英]Updating UI when a model property changes in an ObservableCollection?

I have a view that has a group of images I get from a web service I receive them in a list of this class: 我有一个视图,我从一个Web服务获得一组图像,我在这个类的列表中收到它们:

 public class ImageModel 
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string imageUrl { get; set; }
    }

under each image I show an up-vote button, so I added another bool property to the model above: 在每个图像下我显示一个向上投票按钮,所以我在上面的模型中添加了另一个bool属性:

 public bool UpVoted { get; set; }

the ListView that shows these images is bound to an ObservableCollection<ImageModel > , I want to change the voting icon through a converter that convert the value of UpVoted to the corresponding icon, when the user click the voting icon: a command execute this method: 显示这些图像的ListView绑定到ObservableCollection<ImageModel > ,我想通过将UpVoted的值转换为相应图标的转换器更改投票图标,当用户单击投票图标时:命令执行此方法:

    private void OnVoting(ImageModel image)
    {
        Images.Single(x => x.id == image.id).UpVoted = !image.UpVoted;
    }

the problem is that the UI is not updated, and to make sure that I understood the problem I turned the model to a View model and made the required changes to the UpVoted property (I'm using MVVM light library) 问题是UI没有更新,为了确保我理解了问题,我将模型转换为View模型,并对UpVoted属性进行了必要的更改(我使用的是MVVM光库)

bool upVoted;
        public bool UpVoted
        {
            get { return upVoted; }
            set
            {
                Set(ref upVoted, value);
            }
        }

and it works now, so I need to bind the UpVoted to the UI, so it's updated whenever it changed 它现在可以工作,所以我需要将UpVoted绑定到UI,因此只要它发生变化就会更新

first your model class must inherit from MvxNotifyPropertyChanged 首先,您的模型类必须从MvxNotifyPropertyChanged继承

public class ImageModel : MvxNotifyPropertyChanged
    {
        public int Id { get; set; }
        public string Name { get; set; }
        private bool upVoted ;
        public bool UpVoted 
        {
            get { return upVoted ; }
            set { upVoted = value; RaisePropertyChanged(() => UpVoted ); }
        }
    }

then with MvxValueConverter you ready to go 然后用MvxValueConverter准备好了

Mustafa's answer mentions a class that is specific to MvvmCross library. Mustafa的回答提到了一个特定于MvvmCross库的类。
Another alternative is TinyMvvm . 另一种选择是TinyMvvm

If you wish to write your own MVVM (or understand how MVVM works), the general pattern is to implement INotifyPropertyChanged: Implement Property Change Notification , which I discuss here . 如果您希望编写自己的MVVM(或了解MVVM如何工作),一般模式是实现INotifyPropertyChanged: 实现属性更改通知我在这里讨论

A convenient way to implement INotifyPropertyChanged, is to make a base class that does that implementation, then inherit from that base class. 实现INotifyPropertyChanged的一种便捷方法是创建一个执行该实现的基类,然后从该基类继承。 You can use the code in that sample as your base class. 您可以使用该示例中的代码作为基类。 Or use a slightly different implementation, that avoids having to manually pass the property name as a string: 或者使用稍微不同的实现,避免必须手动将属性名称作为字符串传递:

using System.ComponentModel;
using System.Runtime.CompilerServices;

// Use this as base class for all your "view model" classes.
// And possibly for your (domain) model classes.
// E.g.:  "public class MyLoginViewModel : HasNotifyPropertyChanged".
// OR     "public class MyLoginModel : HasNotifyPropertyChanged".
// Give it whatever name you want, for ViewModels I suggest "ViewModelBase".
public class HasNotifyPropertyChanged : INotifyPropertyChanged
{
    // --- This is pattern to use to implement each property. ---
    //     This works for any property type: int, Color, etc.
    //     What's different from a standard c# property, is the "SetProperty" call.
    //     You will often write an IValueConverter (elsewhere) to use in XAML to convert from string to your property type,
    //     or from your property type to a type needed in your UI.
    //     Comment out this example property if you don't need it.
    /// <summary>
    /// Set to "true" at end of your initialization.
    /// Then can use Property Trigger on Ready value=true in XAML to do something when your instance is ready for use.
    /// For example, load something from web, then trigger to update UI.
    /// </summary>
    private bool _ready;
    public bool Ready
    {
        get => _ready;
        set => SetProperty(ref _ready, value);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
    {
        if (property == null || !property.Equals(value))
        {
            property = value;
            RaisePropertyChanged(propertyName);
        }
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Again, an alternative to the above code is to use an existing MVVM library. 同样,上述代码的替代方法是使用现有的MVVM库。

For another alternative, that doesn't require writing "SetProperty(..)" or "OnPropertyChanged(..)" in all of your property setters , google for info about using Fody/PropertyChanged . 对于另一种选择, 这不需要在所有属性设置器中写入“SetProperty(..)”或“OnPropertyChanged(..)” ,谷歌有关使用Fody / PropertyChanged的信息 Then you wouldn't need any of the above code; 那你就不需要上面的代码了; your class would simply inherit from INotifyPropertyChanged . 你的类只会从INotifyPropertyChanged继承。 (And in app startup, you call a method that "injects" the needed logic into all properties of all INotifyPropertyChanged classes.) (在app启动时,你调用一个方法,将所需的逻辑“注入”所有INotifyPropertyChanged类的所有属性。)

Acknowledgement: The code pattern in example above is based on one of the open source libraries. 致谢:上面示例中的代码模式基于其中一个开源库。 It might be from TinyMvvm. 它可能来自TinyMvvm。

you do not say which sort of container that you are using but not all controls are set to support two way notification by default. 您没有说明您正在使用哪种容器,但并非所有控件都设置为默认支持双向通知。 so you may have to add a 所以你可能需要添加一个

Mode=TwoWay

to get notifications from the back end that data has changed. 从后端获取数据已更改的通知。 Or as the previous answer by Mustafa indicated you may need to verify that your class is implementing the InotifyPropertyChanged event with mvvm light. 或者,正如Mustafa先前的回答所示,您可能需要验证您的班级是否正在使用mvvm light实现InotifyPropertyChanged事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 的ObservableCollection <DateTime> 并在项目更改时更新用户界面 - ObservableCollection<DateTime> and updating the UI when the item changes Winui3 桌面; ObservableCollection,在属性更改时更新 UI? 从不同线程更新 - Winui3 Desktop; ObservableCollection, updating UI when property changes? Updating from different thread 属性更改时UI不更新 - UI not updating when a property changes 当 static ObservableCollection 的元素的属性被修改时更新 UI - Updating UI when a property of an element of a static ObservableCollection is modified 从UI更改ObservableCollection而不更新Bound Collection - Changes to ObservableCollection from UI not updating the Bound Collection 基础ObservableCollection更改时,ComboBox项未更新 - ComboBox items not updating when underlying ObservableCollection changes 绑定的ObservableCollection更改时,ListView不更新 - ListView not updating when the bound ObservableCollection changes 当ObservableCollection的值更改时,UI不更新 - UI is not updated when value of ObservableCollection Changes 更改ObservableCollection的内容时难以更新UI? - Difficulty updating UI when contents of ObservableCollection is changed? ObservableCollection中的Property更改时引发事件 - Raising event when Property in ObservableCollection changes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM