2017-01-23 38 views
0

我有一个Car类。最有效的通知视图方式(WPF/C#)

class Car 
{ 
    string ModelNum; 
} 

然后,我有车实例

class CarInstance 
{ 
    string RegistrationNum; 
} 

有我的视图模型汽车的几个实例。

ViewModel(Car car) 
{ 
    CarInstance Ins = car.GetInstance(); 
} 

问题:说汽车本身在改变,它需要通知改变的视图模型。什么是最有效的方式来做到这一点。我知道我可以使用事件(包括PRISM中的eventaggregator)。我想知道是否有更快的方法来做到这一点。

可以调用多个订阅者的Action参数?任何这样的想法?

所有伪代码。

+2

您是否遇到过INotifyPropertyChanged? –

+0

是的。两个问题。比事件表现更好吗?将属性通知放入Car类(它是一个业务对象,并且通知属性已更改是一个UI特定的想法)吗? – Jimmy

+2

我相信是的。还有,它是非常正常的把属性通知放在你的模型类中,比如Car。这些事件是从您的模型属性的setter中引发的。你也可以从你的ViewModel接收通知,但是如果你要在你的UI上绑定这些通知,那么让你的属性设置器中的通知非常重要 –

回答

1

INotifyPropertyChanged比事件更有效吗?

INotifyPropertyChanged接口定义了一个PropertyChanged事件,即它实际上使用事件来通知视图。

说汽车本身在改变,它需要通知视图模型的变化。什么是最有效的方式来做到这一点。我知道我可以使用事件(包括PRISM中的eventaggregator)。我想知道是否有更快的方法来做到这一点。

引发事件将是在大多数情况下,性能方面非常小的,所以你不应该担心这一点:

How much performance overhead is there in using events?

使用事件聚合的好处是,你的类成为与保持对来自每个发布者类别的每个订户的直接参考相比,更宽松地耦合到彼此:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

但是,使用强引用或事件聚合器引发事件是一种好的推荐修补和快速的方式通知外界的变化。

0

它的绝对正常,把属性更改通知在您的模型,如果他们绑定到您的意见。这是MVVM中首选的方法。这是你如何能做到这

using System.ComponentModel; 
using System.ComponentModel.DataAnnotations; 

public class Car: INotifyPropertyChanged 
{ 
    #region Property Changed 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 

    private string _modelNum; 

    public string ModelNum 
    { 
     get{ return _modelNum; } 
     set 
     { 
      _modelNum = value; 
      //this will raise the notification 
      OnPropertyChanged("ModelNum"); 
     } 
    } 
} 

如果这辆车对象绑定到你的视图中,可以

Text="{Binding Car.ModelNum, UpdateSourceTrigger=PropertyChanged}" 

UpdateSourceTrigger =的PropertyChanged将更新每当MODELNAME被更新或将更新MODELNAME每当UI你从UI更新。

0

为notiyfing创建下面的类:

public abstract class Notifier : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private readonly Dictionary<string, object> _properties = new Dictionary<string, object>(); 

    protected T Get<T>([CallerMemberName] string name = null) 
    { 
     Debug.Assert(name != null, "name != null"); 
     object value = null; 
     if (_properties.TryGetValue(name, out value)) 
      return value == null ? default(T) : (T)value; 
     return default(T); 
    } 
    protected void Set<T>(T value, [CallerMemberName] string name = null) 
    { 
     Debug.Assert(name != null, "name != null"); 
     if (Equals(value, Get<T>(name))) 
      return; 
     _properties[name] = value; 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 
    } 
    public void Notify<T>(Expression<Func<T>> memberExpression) 
    { 
     if (memberExpression == null) 
     { 
      throw new ArgumentNullException("memberExpression"); 
     } 
     var body = memberExpression.Body as MemberExpression; 
     if (body == null) 
     { 
      throw new ArgumentException("Lambda must return a property."); 
     } 

     var vmExpression = body.Expression as ConstantExpression; 
     if (vmExpression != null) 
     { 
      LambdaExpression lambda = Expression.Lambda(vmExpression); 
      Delegate vmFunc = lambda.Compile(); 
      object sender = vmFunc.DynamicInvoke(); 

      PropertyChanged?.Invoke(sender, new PropertyChangedEventArgs(body.Member.Name)); 
     } 
    } 
} 

您的视图模型应该是这个样子。

public class ViewModel : Notifier 
{ 
    public ObservableCollection<String> Messages 
    { 
     get { return Get<ObservableCollection<String>>(); } 
     set 
     { 
      Set(value); 
      Notify(() => AreThereMessages); 
     } 
    } 

    public bool AreThereMessages => Messages?.Count > 0; 
} 

上面的Notifier类不需要任何私有变量。

吸气剂:get { return Get<T>(); }

设置器:get { Set(value); }

通知其他属性:Notify(() => OtherProperty);

实施例视图:

<DataGrid ItemsSource="{Binding Messages}"/> 
<Button IsEnabled="{Binding AreThereMessages}"/> 

上述代码通知按钮,如果消息集合为空或不。 这是我知道处理你的viewmodel没有额外的库最简单的方法。