加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用MVVM更新相关属性

发布时间:2020-12-15 04:10:12 所属栏目:百科 来源:网络整理
导读:我的viewmodel的一些属性: public ObservableCollectionTask Tasks { get; set; }public int Count{ get { return Tasks.Count; }}public int Completed{ get { return Tasks.Count(t = t.IsComplete); }} 当任务更改时,更新这些属性的最佳方法是什么? 我
我的viewmodel的一些属性:
public ObservableCollection<Task> Tasks { get; set; }

public int Count
{
    get { return Tasks.Count; }
}

public int Completed
{
    get { return Tasks.Count(t => t.IsComplete); }
}

当任务更改时,更新这些属性的最佳方法是什么?

我目前的方法:

public TaskViewModel()
{
    Tasks = new ObservableCollection<Task>(repository.LoadTasks());
    Tasks.CollectionChanged += (s,e) => 
        {
            OnPropertyChanged("Count");
            OnPropertyChanged("Completed");
        };
}

有没有更优雅的方式来做到这一点?

解决方法

对于Count来说,你根本不用这样做.只需绑定到Tasks.Count,并且您的绑定将被ObservableCollection通知更改.

完成是一个不同的故事,因为这是在ObservableCollection之外.但是,从抽象/接口级别来看,您确实希望“完成”是“任务”集合的属性.

为此,我认为更好的方法是为您的Tasks属性创建“sub”视图模型:

public class TasksViewModel : ObservableCollection<Task>
{
    public int Completed
    {
        get { return this.Count(t => t.IsComplete); }
    }

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
        if(e.PropertyName == "Count") NotifyCompletedChanged();
    }

    protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        base.OnCollectionChanged(e);
        NotifyCompletedChanged();
    }

    void NotifyCompletedChanged()
    {
        OnPropertyChanged(_completedChangedArgs);
    }
    readonly PropertyChangedEventArgs _completedChangedArgs = new PropertyChangedEventArgs("Completed");
}

这给了ObservableCollection的所有好处,并且有效地使Completed属性成为它的一部分.我们仍然没有捕获完成项目数量真正改变的情况,但是我们已经减少了冗余通知的数量.

现在viewmodel只有属性:

public TasksViewModel Tasks { get; set; }

…并且您可以轻松绑定到任务,Tasks.Count和Tasks.Completed.

或者,如果您希望在“主”视图模型中创建这些其他属性,则可以使用这个概念来创建一个子类的ObservableCollection< T>使用某种方法创建一个可以传入Action< string>代表,将代表在主视图模型上提出属性更改通知,以及一些属性名称列表.然后,该集合可以有效地提高视图模型上的属性更改通知:

public class ObservableCollectionWithSubscribers<T> : ObservableCollection<T>
{
    Action<string> _notificationAction = s => { }; // do nothing,by default
    readonly IList<string> _subscribedProperties = new List<string>();

    public void SubscribeToChanges(Action<string> notificationAction,params string[] properties)
    {
        _notificationAction = notificationAction;

        foreach (var property in properties)
            _subscribedProperties.Add(property);
    }


    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
        NotifySubscribers();
    }

    protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        base.OnCollectionChanged(e);
        NotifySubscribers();
    }

    void NotifySubscribers()
    {
        foreach (var property in _subscribedProperties)
            _notificationAction(property);
    }
}

您甚至可以将属性类型保留为ObservableCollection< Task>.

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        var tasks = new ObservableCollectionWithSubscribers<Task>();
        tasks.SubscribeToChanges(Notify,"Completed");
        Tasks = tasks;
    }

    public ObservableCollection<Task> Tasks { get; private set; }

    public int Completed
    {
        get { return Tasks.Count(t => t.IsComplete); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void Notify(string property)
    {
        var handler = PropertyChanged;
        if(handler != null) handler(this,new PropertyChangedEventArgs(property));
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读