CollectionType 依赖属性

发布于 2024-09-14 05:27:14 字数 2593 浏览 3 评论 0原文

基于本教程:

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

我已经创建了这样的用户控件:

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 code-behind:< /strong>

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???
 }
 }

我想稍后像这样使用用户控件:

 <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>

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

Based on this tutorial:

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

I've created my usercontrol like this:

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 code-behind:

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???
 }
 }

I want to later use the usercontrol like this:

 <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>

In the above code i've added a callback function in my usercontrol so that i can add the new items to the container control "tpControl" declared in the xaml. However when the callback function is triggered the new value is empty. And the question here is why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浅黛梨妆こ 2024-09-21 05:27:14

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

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

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

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

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

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

Are you actually seeing e.NewValue as null or as an empty collection?

In your code you're setting a default value for the property to an ObservableCollection instance (which you generally shouldn't do for reference types - just use null) and then assigning another instance of the ObservableCollection in your control's instance constructor, which is triggering the Changed callback. At this point you are now assigning this new empty collection, which is what you should be seeing for e.NewValue.

If you want to access the items declared in XAML you need to wait until after they have been added to the collection. Adding the items will not cause the change handler for the property to fire because you're not assigning a new collection to the DP. You can either use a handler for a different event that occurs later (like Loaded)

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

or attach a CollectionChanged handler to the e.NewValue instance which will be called each time an item is added, removed, moved, etc.

    var newValue = e.NewValue as ObservableCollection<ThirdPartyClass>;
    newValue.CollectionChanged += (sender, args) => { DoSomething(TestItems); };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文