[英]WPF Custom Control - How to properly loop through and display child content
试图编写一个自定义控件来允许子内容的集合。 最终目标是根据自定义附加依赖属性对子元素进行一些功能过滤; 然而,在此之前,我为收集和重新显示子 UIElements 所做的任何尝试都以在 XAML 解析/显示期间出现异常而告终。
我有一个类CustomFilter : Control
在附近的 xaml 文件中具有关联的默认样式。 它具有 Children 的依赖属性,该属性当前收集 UIElementCollection 中的子元素。
我相信我的问题可能是我试图呈现孩子的集合。 我知道的在 XAML 中循环内容的唯一方法涉及使用 ItemsControl,我将我的 Children 集合作为 ItemsSource 传递给它,这感觉相当落后(使用 UIElements 作为数据模型?)
之后,我们尝试通过 ItemTemplate 内的内容展示器呈现元素。 我已经在许多其他示例中看到使用内容展示器呈现控件子级,所以我希望这可能至少部分正确(尽管所有都只使用单个元素)。
样本类
[ContentProperty(nameof(Children))]
public class CustomFilter : Control
{
static CustomFilter()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomFilter), new FrameworkPropertyMetadata(typeof(CustomFilter)));
}
public CustomFilter()
{
Children = new UIElementCollection(this, this);
}
public static readonly DependencyProperty ChildrenProperty = DependencyProperty.Register(nameof(Children), typeof(UIElementCollection), typeof(CustomFilter), new FrameworkPropertyMetadata(RefreshFilter));
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public UIElementCollection Children
{
get { return (UIElementCollection)GetValue(ChildrenProperty); }
private set { SetValue(ChildrenProperty, value); }
}
}
示例模板
<Style TargetType="{x:Type local:CustomFilter}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomFilter}">
<StackPanel>
<ItemsControl ItemsSource="{TemplateBinding Children}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<ContentPresenter Content="{Binding}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
用例
<local:CustomFilter>
<TextBlock Text="X"/>
<TextBlock Text="Y"/>
<TextBlock Text="Z"/>
</local:CustomFilter>
尝试运行使用此控件会导致它在到达 ItemsControl 时失败,而不会到达 ItemTemplate,但以下情况除外:
ArgumentException: Specified Visual is already a child of another Visual or the root of a CompositionTarget.
我试图为 Children 创建一个包装类,将一个孩子传递给包装的每个实例,并将其作为 ItemsSource 绑定到它 - 它成功地循环遍历 ItemTemplate,但尝试在包装的子元素上使用 ContentPresenter为我提供以下异常:
ArgumentException: Must disconnect specified child from current parent Visual before attaching to new parent Visual.
为什么要使用UIElementCollection
而不是List<UIElement>
? 您不应该绑定到模板中的UIElementCollection
。
如果您定义List<UIElement>
依赖项属性,您的示例应该可以工作:
[ContentProperty(nameof(Children))]
public class CustomFilter : Control
{
static CustomFilter()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomFilter), new FrameworkPropertyMetadata(typeof(CustomFilter)));
}
public CustomFilter()
{
SetValue(ChildrenPropertyKey, new List<UIElement>());
}
private static readonly DependencyPropertyKey ChildrenPropertyKey =
DependencyProperty.RegisterReadOnly(
nameof(Children),
typeof(List<UIElement>),
typeof(CustomFilter),
new FrameworkPropertyMetadata(new List<UIElement>())
);
public static readonly DependencyProperty ChildrenProperty =
ChildrenPropertyKey.DependencyProperty;
public List<UIElement> Children
{
get { return (List<UIElement>)GetValue(ChildrenProperty); }
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.