集合类型附加属性

时间:2017-11-24 10:18:50

标签: c# binding uwp dependency-properties attached-properties

我想通过收集FrameworkElement的集合类型附加属性扩展ButtonDependencyObjects类。

难点在于对​​集合项的绑定不起作用:没有显示调试或运行时错误,但从未调用绑定源。

我注意到集合类型附加属性不继承自类DependencyObject

我想DataContext属性将由任何子DependencyObject对象继承(只要父对象也是DependencyObject对象)。由于collection-type附加属性不从DependencyObject继承,因此DataContext属性继承不会发生。

  1. 我想知道为什么DependencyObject的实例可以继承DataContext属性,因为DataContextFrameworkElement中定义的属性? DependencyObject如何管理DataContext查找?
  2. 为什么指定ElementName=PageName的绑定源不起作用(例如{Binding MyProperty="{Binding DataContext.PropertySource1, ElementName=PageName})?如果DependencyObject也负责ElementName查询,它是如何做到的?
  3. 是否有继承DependencyObject的UWP集合? (在WPF中有FreezableCollection<T>类但我在UWP环境中找不到吊坠。)
  4. 下面的XAML标记显示了一个示例扩展,其中Binding不起作用。

    <Button Name="Button">
        <ext:MyExtension.MyCollection>
            <ext:MyDependencyObject MyProperty="{Binding PropertySource1}"/>
            <ext:MyDependencyObject MyProperty="{Binding PropertySource1}"/> 
        </ext:MyExtension.MyCollection>
    </Button>
    

    如果我对非集合类型附加属性执行以下扩展,则可以正确解析绑定。

    <Button Name="Button">
        <ext:MyExtension.MyProperty>
            <ext:MyDependencyObject MyProperty="{Binding PropertySource1}"/>
        </ext:MyExtension.MyProperty>
    </Button>
    

    下面的代码显示了一个示例集合类型附加属性实现。考虑附加属性类还包含非colleciton类型附加属性的定义(它可以正确地绑定)。

    public class MyDependencyObject: DependencyObject
    {
        public object MyProperty
        {
            get { return (object)GetValue(MyPropertyProperty ); }
            set { SetValue(MyPropertyProperty , value); }
        }
        public static readonly DependencyProperty MyPropertyProperty =
            DependencyProperty.Register("MyProperty", typeof(object), typeof(MyProperty), null);
    }
    
    public class MyPropertyCollection : ObservableCollection<MyDependencyObject> { }
    
    public static class MyExtension
    {
        // Collection-type AttachedProperty with DependencyObject items
    
        public static MyPropertyCollection GetMyPropertyCollection(DependencyObject obj)
        {
            MyPropertyCollection collection = (MyPropertyCollection )obj.GetValue(MyCollectionProperty );
            if (collection == null)
            {
                collection = new MyPropertyCollection();
    
                collection.CollectionChanged +=
                    (sender, e) =>
                    {
                        //intiailization of elements possible
                    };
    
    
                obj.SetValue(MappingsProperty, collection);
            }
    
            return collection;
        }
    
        public static void SetMyPropertyCollection(DependencyObject obj, MyPropertyCollection value)
        {
            obj.SetValue(MyCollectionProperty , value);
        }
    
        public static readonly DependencyProperty MyCollectionProperty =
            DependencyProperty.RegisterAttached("MyCollection", typeof(MyPropertyCollection), typeof(MyExtension), null);
    
    
        // DependencyObject-type AttachedProperty
    
        public static MyProperty GetMapping(DependencyObject obj)
        {
            return (MyProperty )obj.GetValue(MyPropertyProperty );
        }
    
        public static void SetMapping(DependencyObject obj, MyProperty value)
        {
            obj.SetValue(MyPropertyProperty , value);
        }
    
        public static readonly DependencyProperty MyPropertyProperty =
            DependencyProperty.RegisterAttached("MyProperty", typeof(MyDependencyObject), typeof(MyExtension), null);
    
    }
    

1 个答案:

答案 0 :(得分:2)

在WPF中,可以使用FreezableCollection<T>或继承Freezable类,IList<T>IList

  1. DependencyObject继承它,因为无法访问DependencyObject的两个必需方法,但Freezable有一个包装器。
  2. 根据需要实施IList<T>IList
  3. 将新元素添加到集合调用OnFreezablePropertyChanged(null, newItem)
  4. 从中删除元素时,请致电OnFreezablePropertyChanged(item, null)
  5. OnFreezablePropertyChanged方法在内部将调用两个DependencyObject方法来提供或删除继承上下文(source)。

    但是在UWP中没有Freezable并且没有这样的方法,所以在Windows 10.0.10240.0之前它是不可能的。但是,如果您的目标是v10.0.10240.0或更高版本,则应使用针对行为制作的DependencyObjectCollection

      

    DependencyObjectCollection类的目的主要是支持行为的工具和可移植性。行为是一种完全在XAML中定义UI元素的某些基本交互的技术,无需事件处理程序和代码隐藏。

    因此,在UWP和WPF中,只有当子节点是逻辑/可视子节点或它们是依赖属性值时,才能为子节点提供继承上下文。因此,Binding设置ElementName在您的案例中使用时不起作用。当绑定附加到依赖项对象而非编译时,ElementName属性用于在运行时解析对象。

    UWP绑定的工作方式与WPF绑定类似,例如,请参阅第二个平台的ElementObjectRef.GetObject