CollectionType依赖项属性

时间:2010-08-11 12:39:18

标签: wpf user-controls dependency-properties

基于本教程:

http://www.dotnetfunda.com/articles/article961-wpf-tutorial--dependency-property-.aspx

我已经像这样创建了我的usercontrol:

usercontrol xaml:

 <UserControl x:Class="PLVS.Modules.Partner.Views.TestControl"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:tp="http://thirdparty.com/controls"
       x:Name="UC">
  <tp:ContainerControl x:Name="tpControl">
    <tp:ContainerControl.Items>
      <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText"/>
      </tp:SomeItem>
    </ig:TabItemEx>
 </tp:ContainerControl.Items>
  </tp:ContainerControl>
</UserControl> 

usercontrol代码隐藏:

public partial class TestControl : UserControl
{
 public TestControl()
    {
  InitializeComponent();
  SetValue(TestItemsPropertyKey, new ObservableCollection<ThirdPartyClass>());
 }

    public ObservableCollection<ThirdPartyClass> TestItems
    {
      get 
      { 
        return (ObservableCollection<ThirdPartyClass>)GetValue(TabItemsProperty); 
      }
    }

    public static readonly DependencyPropertyKey TestItemsPropertyKey =
      DependencyProperty.RegisterReadOnly("TestItems", typeof(ObservableCollection<ThirdPartyClass>), typeof(TestControl), new UIPropertyMetadata(new ObservableCollection<ThirdPartyClass>(), TestItemsChangedCallback));

 public static readonly DependencyProperty TestItemsProperty = TestItemsPropertyKey.DependencyProperty;

 private static void TestItemsChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs e)
 {
      TestControl ib = obj as TestControl;
  var newNvalue = e.NewValue; // Why is e.NewValue null???
 }
 }

我想稍后使用这样的usercontrol:

 <localControl:TestControl x:Name="testControl">
 <localControl:TestControl.TabItems>
      <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText2"/>
      </tp:SomeItem>
  <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText3"/>
      </tp:SomeItem>
 </tp:ContainerControl.Items>
 </localControl:TestControl>

在上面的代码中,我在我的usercontrol中添加了一个回调函数,这样我就可以将新项添加到xaml中声明的容器控件“tpControl”中。但是,当触发回调函数时,新值为空。这里的问题是为什么?

1 个答案:

答案 0 :(得分:0)

您实际上是将e.NewValue视为null还是空集合?

在您的代码中,您将属性的默认值设置为ObservableCollection实例(通常不应该对引用类型执行 - 只使用null),然后在控件的实例构造函数中指定ObservableCollection的另一个实例,这是触发Changed回调。此时您正在分配这个新的空集合,这是您应该看到的e.NewValue。

如果要访问XAML中声明的项目,则需要等到它们添加到集合中之后。添加项目不会导致属性的更改处理程序触发,因为您没有为DP分配新集合。您可以为稍后发生的其他事件(如已加载)使用处理程序

    Loaded += (sender, e) => { DoSomething(TestItems) };

或将CollectionChanged处理程序附加到e.NewValue实例,每次添加,删除,移动项目时都会调用该实例。

    var newValue = e.NewValue as ObservableCollection<ThirdPartyClass>;
    newValue.CollectionChanged += (sender, args) => { DoSomething(TestItems); };