从XAML(WPF)设置集合DependencyProperty

问题描述:

我创建了一个用户控件(FilterPicker),它具有某个列表作为属性。这是一个依赖项属性,因此可以在使用用户控件时进行设置。从XAML(WPF)设置集合DependencyProperty

public static readonly DependencyProperty StrategiesProperty = DependencyProperty.Register(
     "Strategies", 
     typeof(List<FilterType>), 
     typeof(FilterPicker), 
     new FrameworkPropertyMetadata 
     { 
      DefaultValue = new List<FilterType> { FilterType.Despike }, 
      PropertyChangedCallback = StrategiesChangedCallback, 
      BindsTwoWayByDefault = false, 
     }); 

然后我试图在我使用这个控件的.xaml文件中定义这个列表。

<Filtering:FilterPicker Grid.Row="1" Strategy="{Binding Strategy}"> 
      <Filtering:FilterPicker.Strategies> 
       <Filtering1:FilterType>PassThrough</Filtering1:FilterType> 
       <Filtering1:FilterType>MovingAverage</Filtering1:FilterType> 
       <Filtering1:FilterType>Despike</Filtering1:FilterType> 
      </Filtering:FilterPicker.Strategies> 
     </Filtering:FilterPicker> 

但是,它不起作用。 StrategiesChangedCallBack永远不会被调用。 如果我通过绑定来设置它,它工作正常 - 只是当我尝试在xaml中定义它时。所以这个作品:

<Filtering:FilterPicker Grid.Row="1" Strategy="{Binding Strategy}" Strategies="{Binding AllStrategies}"> 

但不是以前的代码片段。关于我在做什么的任何想法都是错误的?

+3

在XAML中添加的元素被添加到现有的集合,它已设置为属性的默认值。集合实例不会更改,因此不会调用PropertyChangedCallback。您可以使用实现INotifyCollectionChanged接口(例如ObservableCollection)的集合,并为其CollectionChanged事件附加处理程序,而不是List。 – Clemens

+1

除此之外,对集合类型依赖项属性使用默认值有潜在危险,因为拥有的类的所有实例将默认在相同的集合实例上操作,即向一个FilterPicker的Strategies属性中添加元素将影响属性所有其他FilterPickers。 – Clemens

+0

有关如何处理INotifyCollectionChanged,请参阅示例[此答案](http://*.com/a/9128855/1136211)或[this one](http://*.com/a/19558932/1136211)。 – Clemens

从我原来的问题的评论,我能够拼凑一起:

  • 事实上,问题是,我只是听着财产被改变,而不是集合中的对象。
  • 正如我预测的那样,它在同一个集合实例上运行时遇到问题。

最后,我将我的DependencyProperty更改为使用IEnumerable,我在使用FilterPicker UserControl的.xaml中将其定义为StaticResource。

的DependencyProperty:

public static readonly DependencyProperty StrategiesProperty = DependencyProperty.Register(
     "Strategies", 
     typeof(IEnumerable<FilterType>), 
     typeof(FilterPicker), 
     new FrameworkPropertyMetadata 
     { 
      DefaultValue = ImmutableList<FilterType>.Empty, //Custom implementation of IEnumerable 
      PropertyChangedCallback = StrategiesChangedCallback, 
      BindsTwoWayByDefault = false, 
     }); 

使用它:

<Grid.Resources> 
      <x:Array x:Key="FilterTypes" Type="{x:Type Filtering1:FilterType}" > 
       <Filtering1:FilterType>PassThrough</Filtering1:FilterType> 
       <Filtering1:FilterType>MovingAverage</Filtering1:FilterType> 
       <Filtering1:FilterType>Fir</Filtering1:FilterType> 
      </x:Array> 
     </Grid.Resources> 

<Filtering:FilterPicker Grid.Row="1" Strategies="{StaticResource FilterTypes}" />