获取 ItemsControl children 在 WinRT 中继承前台

Get ItemsControl children to inherit foreground in WinRT

在自定义 TemplatedControl 中,我有一个在自定义 TemplatedControl 之外填充的 ItemsControl。我希望 ItemsControl 的(未来)子级自动从 ItemsControl 继承 Foreground 值。

我希望能够从 TemplatedControl 更改前景值,并让子控件也更新它们的前景。

这是我的 ItemsControl:

<ItemsControl x:Name="PrimaryItems" ItemsSource="{TemplateBinding PrimaryItems}" Foreground="{TemplateBinding MyCustomForeground}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

当我使用 TemplatedControl 时,它看起来像这样:

<Grid>
    <Controls:MyCustomControl MyCustomForeground="Blue">
        <Controls:MyCustomControl.PrimaryItems>
            <Button Content="Test button"/>
        </Controls:MyCustomControl.PrimaryItems>
    </Controls:MyCustomControl>
</Grid>

我希望按钮前景自动为蓝色,因为我在 TemplatedControl 中将其设置为 MyCustomForeground。

有什么建议吗?

您试过 {TemplateBinding xxxx} 了吗?

<Controls:MyCustomControl MyCustomForeground="{TemplateBinding Foreground}">
    <Controls:MyCustomControl.PrimaryItems>
        <Button Content="Test button"/>
    </Controls:MyCustomControl.PrimaryItems>
</Controls:MyCustomControl>

我明白了,这很棘手。如果您尝试使用 DependencyProperty 继承,这将不起作用(使用您的 UserControl 的前景 属性):

<UserControl
    x:Class="TestApp1.CustomControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestApp1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400" Foreground="Blue">

    <StackPanel x:Name="PART_Container">
        <Button Content="Test"/>
        <TextBlock Text="Test"/>
    </StackPanel>
</UserControl>

如果您尝试此代码段,按钮的 phone 模板将覆盖 Foreground="Blue",因此它将具有白色(或黑色,具体取决于主题)前景。请注意,Textblock 没有样式,不会显示此行为,它将成功从其父 UserControl 继承蓝色前景。

如何解决这个问题?您似乎声明了一个自定义依赖项 属性 MyCustomForeground,因此您可以在 DependencyPropertyChanged 处理程序中实现一个逻辑。但是每次您的 PrimaryItems 更改时,您还必须应用您的自定义前景。

这是一个工作示例:

public sealed partial class CustomControl : UserControl
{
    public CustomControl()
    {
        this.InitializeComponent();
    }
    public Brush MyCustomForeground
    {
        get { return (Brush)GetValue(MyCustomForegroundProperty); }
        set { SetValue(MyCustomForegroundProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyCustomForeground.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyCustomForegroundProperty =
        DependencyProperty.Register("MyCustomForeground", typeof(Brush), typeof(CustomControl), new PropertyMetadata(null, OnCustomForegroundChanged));

    private static void OnCustomForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CustomControl ctrl = (CustomControl)d;
        ctrl.ApplyCustomForeground();
    }

    public UIElement PrimaryItems
    {
        get { return (UIElement)GetValue(PrimaryItemsProperty); }
        set { SetValue(PrimaryItemsProperty, value); }
    }

    // Using a DependencyProperty as the backing store for PrimaryItems.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PrimaryItemsProperty =
        DependencyProperty.Register("PrimaryItems", typeof(UIElement), typeof(CustomControl), new PropertyMetadata(null, OnPrimaryItemsChanged));

    private static void OnPrimaryItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CustomControl ctrl = (CustomControl)d;
        // PART_Container is where I store my PrimaryItems
        ctrl.PART_Container.Children.Clear();
        ctrl.PART_Container.Children.Add((UIElement)e.NewValue);
        ctrl.ApplyCustomForeground();
    }

    private void ApplyCustomForeground()
    {
        // PART_Container is where I store my PrimaryItems
        foreach (var child in PART_Container.Children)
        {
            // Foreground is inherited by Control or TextBlock, or other classes... 
            // You would be better off using reflection here but that's off topic
            if (child is Control)
            {
                ((Control)child).Foreground = MyCustomForeground;
            }
            else if (child is TextBlock)
            {
                ((TextBlock)child).Foreground = MyCustomForeground;
            }
        }
    }
}