2012-02-03 66 views
3

我想創建一個從標準網格派生的自定義控件。 我添加了一個ObservableCollection作爲自定義控件的DependencyProperty。但是,它的獲取/設置從未達到。我可以在創建與ObservableCollection一起正確使用的DependencyProperty方面有一些指導嗎?DependencyProperty getter/setter未被調用

public class MyGrid : Grid 
{ 
    public ObservableCollection<string> Items 
    { 
     get 
     { 
      return (ObservableCollection<string>)GetValue(ItemsProperty); 
     } 
     set 
     { 
      SetValue(ItemsProperty, value); 
     } 
    } 

public static DependencyProperty ItemsProperty = 
       DependencyProperty.Register("Items", typeof(ObservableCollection<string>), 
     typeof(MyGrid), new UIPropertyMetadata(null, OnItemsChanged)); 

} 
+0

observablecollection應該在您的viewmodel中,而不是您的控件... – thumbmunkeys 2012-02-03 10:15:31

+0

它已經在我的viewmodel中。但是,我如何將它傳遞給網格?網格不應該知道如何處理集合嗎? – phm 2012-02-03 10:18:07

+0

您可以將依賴項屬性定義爲IEnumerable,如[ItemsControl.ItemsSource](http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemssource.aspx)。或者發佈你的代碼,這樣有人可能會發現它有什麼問題。 – Clemens 2012-02-03 10:27:24

回答

8

我建議不使用的ObservableCollection作爲Items依賴屬性的類型。

在這裏有一個ObservableCollection(我猜)的原因是在分配屬性值時,使UserControl能夠附加CollectionChanged處理程序。但ObservableCollection太具體。

WPF中的方法(例如ItemsControl.ItemsSource)是定義一個非常基本的接口類型(如IEnumerable),並且當該屬性被賦值時,找出值集合是否實現了某些更具體的接口。這裏至少應該是INotifyCollectionChanged,但該集合也可能實現ICollectionViewINotifyPropertyChanged。所有這些接口都不是強制性的,這將使您的依賴屬性綁定到各種集合,從普通數組開始到複雜的ItemCollection。然後

OnItemsChanged屬性更改回調應該是這樣的:

private static void OnItemsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
{ 
    MyGrid grid = obj as MyGrid; 

    if (grid != null) 
    { 
     var oldCollectionChanged = e.OldValue as INotifyCollectionChanged; 
     var newCollectionChanged = e.NewValue as INotifyCollectionChanged; 

     if (oldCollectionChanged != null) 
     { 
      oldCollectionChanged.CollectionChanged -= grid.OnItemsCollectionChanged; 
     } 

     if (newCollectionChanged != null) 
     { 
      newCollectionChanged.CollectionChanged += grid.OnItemsCollectionChanged; 

      // in addition to adding a CollectionChanged handler 
      // any already existing collection elements should be processed here 
     } 
    } 
} 

private void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    // handle collection changes here 
} 
+0

太棒了,男人! :-) – zoidbeck 2012-02-03 15:12:41

4

的WPF綁定機制可以繞過你的標準CLR屬性,並直接去依賴屬性訪問器(GetValueSetValue)。

這就是爲什麼邏輯不應放在CLR屬性內部,而應該放在更改後的處理程序中。

<local:MyGrid> 
    <local:MyGrid.Items> 
     <sys:String>First Item</sys:String> 
     <sys:String>Second Item</sys:String> 
    </local:MyGrid.Items> 
</local:MyGrid> 

它實際上是調用得到Items,然後調用Add每個元素:

另外,ObservableCollection<string>將永遠不會被因爲當你使用集合屬性從XAML,像下面的設置。