2017-01-23 35 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沒有額外的庫最簡單的方法。