集合类型附加属性
Collection-Type Attached Properties
我想通过收集 DependencyObjects
的附加收集类型 属性 来扩展 FrameworkElement
元素,例如 Button
class。
困难在于对集合项的绑定不起作用:没有出现调试或运行时错误,但从未调用绑定的源代码。
我注意到附加的集合类型 属性 没有继承自 class DependencyObject
。
我猜 DataContext
属性 将被任何子 DependencyObject
对象继承(只要父对象也是 DependencyObject
对象)。由于附加的集合类型 属性 不从 DependencyObject
继承,因此不会发生 DataContext
属性 继承。
- 我想知道为什么
DependencyObject
的实例可以继承 DataContext
属性 因为 DataContext
是 FrameworkElement
中定义的 属性? DependencyObject
如何管理 DataContext
查找?
- 为什么用
ElementName=PageName
指定绑定源也不起作用(例如 {Binding MyProperty="{Binding DataContext.PropertySource1, ElementName=PageName}
)?如果 DependencyObject
也负责 ElementName
查找,它是怎么做到的?
- 是否有继承
DependencyObject
的UWP合集? (在WPF中有FreezableCollection<T>
class但是我在UWP环境下找不到挂件。)
下面的 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>
下面的代码显示了一个示例集合类型附加 属性 实现。考虑附加的 属性 class 还包含一个非集合类型附加的定义 属性(与绑定一起工作)。
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);
}
在 WPF 中,可以通过使用 FreezableCollection<T>
或继承 Freezable
class、IList<T>
和 IList
:
- 从
DependencyObject
继承它,因为无法访问 DependencyObject
的两个必需方法,但是 Freezable
对它们进行了包装。
- 根据需要实施
IList<T>
和 IList
。
- 向集合中添加新元素时调用
OnFreezablePropertyChanged(null, newItem)
。
- 从中删除元素时调用
OnFreezablePropertyChanged(item, null)
。
OnFreezablePropertyChanged
方法内部会调用DependencyObject
的两个方法来提供或移除继承上下文(source)。
但是在 UWP 中没有 Freezable
也没有这样的方法,所以在 Windows 10.0.10240.0 之前是不可能的。但是,如果您的目标是 v10.0.10240.0 或更高版本,您应该使用针对行为的 DependencyObjectCollection
。
The purpose of the DependencyObjectCollection class is mainly to support the tooling and portability of behaviors. Behaviors are a technique for defining certain basic interactions of a UI element entirely in XAML, without requiring an event handler and code-behind.
因此,在 UWP 和 WPF 中,仅当子项是 logical/visual 个子项或者它们是依赖项 属性 值时,才能向子项提供继承上下文。因此,在您的案例中使用 Binding
和 set ElementName
时不起作用。 ElementName
属性 用于在绑定附加到依赖对象而不是编译时在运行时解析对象。
UWP 绑定的工作方式类似于 WPF 绑定,因此例如请参阅第二个平台的 ElementObjectRef.GetObject
。
我想通过收集 DependencyObjects
的附加收集类型 属性 来扩展 FrameworkElement
元素,例如 Button
class。
困难在于对集合项的绑定不起作用:没有出现调试或运行时错误,但从未调用绑定的源代码。
我注意到附加的集合类型 属性 没有继承自 class DependencyObject
。
我猜 DataContext
属性 将被任何子 DependencyObject
对象继承(只要父对象也是 DependencyObject
对象)。由于附加的集合类型 属性 不从 DependencyObject
继承,因此不会发生 DataContext
属性 继承。
- 我想知道为什么
DependencyObject
的实例可以继承DataContext
属性 因为DataContext
是FrameworkElement
中定义的 属性?DependencyObject
如何管理DataContext
查找? - 为什么用
ElementName=PageName
指定绑定源也不起作用(例如{Binding MyProperty="{Binding DataContext.PropertySource1, ElementName=PageName}
)?如果DependencyObject
也负责ElementName
查找,它是怎么做到的? - 是否有继承
DependencyObject
的UWP合集? (在WPF中有FreezableCollection<T>
class但是我在UWP环境下找不到挂件。)
下面的 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>
下面的代码显示了一个示例集合类型附加 属性 实现。考虑附加的 属性 class 还包含一个非集合类型附加的定义 属性(与绑定一起工作)。
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);
}
在 WPF 中,可以通过使用 FreezableCollection<T>
或继承 Freezable
class、IList<T>
和 IList
:
- 从
DependencyObject
继承它,因为无法访问DependencyObject
的两个必需方法,但是Freezable
对它们进行了包装。 - 根据需要实施
IList<T>
和IList
。 - 向集合中添加新元素时调用
OnFreezablePropertyChanged(null, newItem)
。 - 从中删除元素时调用
OnFreezablePropertyChanged(item, null)
。
OnFreezablePropertyChanged
方法内部会调用DependencyObject
的两个方法来提供或移除继承上下文(source)。
但是在 UWP 中没有 Freezable
也没有这样的方法,所以在 Windows 10.0.10240.0 之前是不可能的。但是,如果您的目标是 v10.0.10240.0 或更高版本,您应该使用针对行为的 DependencyObjectCollection
。
The purpose of the DependencyObjectCollection class is mainly to support the tooling and portability of behaviors. Behaviors are a technique for defining certain basic interactions of a UI element entirely in XAML, without requiring an event handler and code-behind.
因此,在 UWP 和 WPF 中,仅当子项是 logical/visual 个子项或者它们是依赖项 属性 值时,才能向子项提供继承上下文。因此,在您的案例中使用 Binding
和 set ElementName
时不起作用。 ElementName
属性 用于在绑定附加到依赖对象而不是编译时在运行时解析对象。
UWP 绑定的工作方式类似于 WPF 绑定,因此例如请参阅第二个平台的 ElementObjectRef.GetObject
。