1

我有一個基礎的DependencyObject類在那裏我有需要的對象的方法的發送對象獲取屬性名稱,獲取的屬性,併爲每個屬性,即實現INotifyPropertyChanged一個類型,我添加一個新的PropertyChangedEventHandler。現在在處理程序方法中,它獲取對象「sender」和PropertyChangedEventArgs「e」的參數。我的問題是,有誰知道如何動態獲取屬性名稱,如果發件人是實現INotifyPropertyChanged類型的屬性。如何從INotifyPropertyChanged的PropertyChanged事件

這裏是我的工作:

public class BaseDependencyObject : DependencyObject, INotifyPropertyChanged 
{ 
    public BaseDependencyObject() 
    { 

    } 

    protected void SetValues(Object thisObject, Object entity) 
    { 
     try 
     { 
      PropertyInfo[] properties = entity.GetType().GetProperties(); 
      foreach (PropertyInfo property in properties) 
      { 
       var value = property.GetValue(entity, null); 
       var valueIsEntity = value is System.ServiceModel.DomainServices.Client.Entity; 
       var thisObjectsProperty = thisObject.GetType().GetProperty(property.Name); 

       if (thisObjectsProperty != null && value != null) 
       { 
        if (valueIsEntity) 
        { 
         if (thisObjectsProperty.PropertyType.GetInterface("INotifyPropertyChanged", true) != null) 
         { 
          var propertyInstance = Activator.CreateInstance(thisObjectsProperty.PropertyType); 

          ((INotifyPropertyChanged)propertyInstance).PropertyChanged += new PropertyChangedEventHandler(Object_PropertyChanged); 
         } 

         SetValues(thisObjectsProperty, value); 
        } 

        else if (thisObjectsProperty.PropertyType.GetInterface("ICollection", true) != null 
         && thisObjectsProperty.PropertyType.GetGenericArguments().Count() > 0) 
        { 
         Type genericType = thisObjectsProperty.PropertyType.GetGenericArguments()[0]; 

         var observableCollection = Activator.CreateInstance(thisObjectsProperty.PropertyType) as IList; 

         if (observableCollection is INotifyCollectionChanged) 
          ((INotifyCollectionChanged)observableCollection).CollectionChanged += this.Object_CollectionChanged; 

         if (observableCollection is INotifyPropertyChanged) 
          ((INotifyPropertyChanged)observableCollection).PropertyChanged += new PropertyChangedEventHandler(Object_PropertyChanged); 

         foreach (var item in (IEnumerable)value) 
         { 
          var newItem = Activator.CreateInstance(genericType); 

          if (newItem != null) 
          { 
           SetValues(newItem, item); 
           observableCollection.Add(newItem); 
          } 
         } 
        } 

        else 
        { 
         thisObjectsProperty.SetValue(thisObject, value, null); 

        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

    protected void Object_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     switch (e.Action) 
     { 
      case NotifyCollectionChangedAction.Add: 
       foreach (var item in e.NewItems) 
       { 
        if (item is INotifyPropertyChanged) 
        { 
         ((INotifyPropertyChanged)item).PropertyChanged += new PropertyChangedEventHandler(Object_PropertyChanged); 
        } 
       } 
       break; 

      case NotifyCollectionChangedAction.Remove: 
       foreach (var item in e.OldItems) 
       { 
        if (item is INotifyPropertyChanged) 
        { 
         ((INotifyPropertyChanged)item).PropertyChanged -= this.Object_PropertyChanged; 
        } 
       } 
       break; 
     } 

    } 

    protected void Object_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     this.NotifyPropertyChanged(e.PropertyName); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void NotifyPropertyChanged(string propertyName) 
    { 
     var handler = PropertyChanged; 

     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 

    } 
} 

setValues方法將的第一個參數是將在視圖模型中使用的DependencyObject的類型。第二個參數是從DomainService的Context.LoadOperation返回的實體。

我的問題歸結爲當INotifyCollectionChanged.CollectionChanged觸發時,我需要能夠用集合的屬性名稱引發PropertyChanged事件。所以如果有人有任何建議,我將不勝感激。提前致謝。

編輯
找出如何獲取觸發事件的屬性名稱。這裏是我的PropertyChangedEventHandler的編輯版本。

protected void Object_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     var properties = this.GetType().GetProperties().Where(x => x.PropertyType == sender.GetType()).ToArray(); 

     foreach (var property in properties) 
     { 
      this.NotifyPropertyChanged(property.Name); 
     } 

     //this.NotifyPropertyChanged(e.PropertyName); 
    } 

基本上這就是我要找的東西,但偶然我還沒有做正確的事。當添加另一個類型的屬性ObservableCollection時,UIElement仍然不會更新。

這是我DependencyObjects的一個例子,視圖模型:

public class LOB : DependencyObject 
{ 
    public Int32 ID 
    { 
     get { return (Int32)GetValue(IDProperty); } 
     set 
     { 
      SetValue(IDProperty, value); 
      NotifyPropertyChanged("ID"); 
     } 
    } 

    public static readonly DependencyProperty IDProperty = 
    DependencyProperty.Register("ID", typeof(Int32), typeof(LOB), null); 

    public ObservableCollection<Group> Groups 
    { 
     get { return (ObservableCollection<Group>)GetValue(GroupsProperty); } 
     set 
     { 
      SetValue(GroupsProperty, value); 
      NotifyPropertyChanged("Groups"); 
     } 
    } 

    public static readonly DependencyProperty GroupsProperty = 
    DependencyProperty.Register("Groups", typeof(ObservableCollection<Group>), typeof(LOB), new PropertyMetadata(null, OnGroupsPropertyChanged)); 

    static void OnGroupsPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     if (e.NewValue != null) 
     { 
      ((INotifyCollectionChanged)e.NewValue).CollectionChanged += new NotifyCollectionChangedEventHandler(((LOB)obj).Object_CollectionChanged); 
      ((INotifyPropertyChanged)e.NewValue).PropertyChanged += new PropertyChangedEventHandler(((LOB)obj).Object_PropertyChanged); 
     } 
     if (e.OldValue != null) 
     { 
      ((INotifyCollectionChanged)e.OldValue).CollectionChanged -= ((LOB)obj).Object_CollectionChanged; 
      ((INotifyPropertyChanged)e.OldValue).PropertyChanged -= ((LOB)obj).Object_PropertyChanged; 
     } 
    } 

} 

public class Group : DependencyObject 
{ 
    public Int32 ID 
    { 
     get { return (Int32)GetValue(IDProperty); } 
     set 
     { 
      SetValue(IDProperty, value); 
      NotifyPropertyChanged("ID"); 
     } 
    } 

    public static readonly DependencyProperty IDProperty = 
    DependencyProperty.Register("ID", typeof(Int32), typeof(Group), null); 

    public String GroupName 
    { 
     get { return (String)GetValue(GroupNameProperty); } 
     set 
     { 
      SetValue(GroupNameProperty, value); 
      NotifyPropertyChanged("GroupName"); 
     } 
    } 

    public static readonly DependencyProperty GroupNameProperty = 
    DependencyProperty.Register("GroupName", typeof(String), typeof(Group), null); 

} 

public class MyViewModel : DependencyObject 
{ 
    public static readonly DependencyProperty LobCollectionProperty = 
     DependencyProperty.Register("LobCollection", 
      typeof(ObservableCollection<LOB>), 
      typeof(MyViewModel), 
      new PropertyMetadata(null, LobCollectionPropertyChanged)); 

    public ObservableCollection<LOB> LobCollection 
    { 
     get { return (ObservableCollection<MainBusinessLine>)GetValue(LobCollectionPropertyChanged); } 
     set 
     { 
      SetValue(MainBusinessLineCollectionProperty, value); 
      NotifyPropertyChanged("LobCollection"); 
     } 
    } 

    static void LobCollectionPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     var viewModel = obj as MyViewModel; 

     if (viewModel == null) 
      return; 

     if (e.OldValue != null) 
     { 
      ((INotifyCollectionChanged)e.OldValue).CollectionChanged -= viewModel.LobCollection_Changed; 
     } 

     if (e.NewValue != null) 
     { 
      ((INotifyCollectionChanged)e.NewValue).CollectionChanged += viewModel.LobCollection_Changed; 
     } 

    } 

    void LobCollection_Changed(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     NotifyPropertyChanged("LobCollection"); 
    } 
} 
+0

讓我確信我正確理解你的問題:你有這個類:「公共類Foo:INotifyPropertyChanged的{INotifyCollectionChanged收集;}」,而當CollectionChanged事件觸發,你想PropertyChanged事件火在擁有的類。那是對的嗎? – 2010-11-02 17:18:46

+0

是的,你是對的。另外我編輯我的原始帖子,以顯示更新版本,它做了一些什麼。當然,這不是最好的解決方案,但目前我只想添加到另一個可觀察集合中的可觀察集合中。 – jhorton 2010-11-02 17:44:57

+0

您在LOB和Group課程中所做的事情對我來說最有意義。在基類中處理它肯定是可能的,但是將DependancyProperty和INotifyPropertyChanged混合使用會讓它更難。另外,請注意,從技術上講,我認爲你沒有遵循INotifyPropertyChanged的合同:該屬性的值沒有改變,它內部的集合具有。這樣做的標準方法是讓CollectionChanged事件觸發,然後離開它。 – 2010-11-02 18:40:32

回答

2

上述的對話後,這是相當沒有實際意義,但我想過我會如何實現該發射的PropertyChanged事件時,集合的基類在由子類定義的屬性中更改。正如我所說,這有點不標準,但這是我的做法。

class FancyCollectionAndPropertyChangedBase : INotifyPropertyChanged 
{ 
    private Dictionary<ICollectionChanged, String> collectionNameLookup = new Dictionary<ICollectionChanged, String>(); 

    protected FancyCollectionAndPropertyChangedBase() 
    { 
     this.PropertyChanged += MyPropertyChanged; 
    } 

    private void MyPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if(this.collectionNameLookup.ContainsValue(e.PropertyName) 
     { 
      KeyValuePair<INotifyCollectionChanged, String> oldValue = this.collectionNameLookup.First(kvp => kvp.Value == e.Name); 
      oldValue.Key -= MyCollectionChanged; 
      this.collecitonNameLookup.Remove(oldValue.Key); 

      INotifyCollectionChanged collection = this.GetType().GetProperty(e.PropertyName, BindingFlags.FlattenHierarchy).GetValue(this, null); 
      collection.CollectionChanged += MyCollectionChanged; 
      this.collectionNameLookup.Add(collection, e.Name); 
     } 
     else if(typeof(INotifyCollectionChanged).IsAssignableFrom(this.GetType().GetProperty(e.PropertyName, BindingFlags.FlattenHierarchy).PropertyType)) 
     { 
      // Note: I may have gotten the IsAssignableFrom statement, above, backwards. 
      INotifyCollectionChanged collection = this.GetType().GetProperty(e.PropertyName, BindingFlags.FlattenHierarchy).GetValue(this, null); 
      collection.CollectionChanged += MyCollectionChanged; 
      this.collectionNameLookup.Add(collection, e.Name); 
     } 
    } 

    private void MyCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     this.NotifyPropertyChanged(this.collectionNameLookup[sender]; 
    } 
} 
+0

David,我只是想讓你知道我使用了你上面發佈的代碼的基礎,並將它實現到了我的Base類中。現在一切正常。我非常感謝你花時間幫助我解決這個問題。我將這個標記爲答案,因爲所有事物的混合物都變成了詭計。另外,我從DependencyObject中刪除了繼承,並僅實現了INotify接口。如果將來有人需要查看完成的代碼,我很樂意發佈。再次感謝。 – jhorton 2010-11-03 15:32:13

相關問題