如何将 DataTrigger 从 resource-defined 样式绑定到 Child 属性?

How would you bind a DataTrigger to a Child property from a resource-defined Style?

如何根据 child 属性的变化设置元素样式?我会接受不同的方法,但期望的结果只是 parent 属性 以某种方式设置,只要 child 属性 (IsPressed) 为真。

如果我们用 in-line 样式设置一个命名项目的样式,我们可以使用 ElementName 简单地标识我们的 child,但我们甚至可以不那么具体并使用 Child.IsPressed:

<Border Name="parentBorder" Padding="20">
    <Button Name="childButton" Content="Don't Push Me Bro"/>
    <Border.Style>
        <!--Now how can I do this from a static resource where I don't know the elementname?-->
        <Style TargetType="Border">
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Child.IsPressed}" Value="True">
                     <Setter Property="Background" Value="Blue"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
</Border>

但是因为我想重用样式和几个边框样式我想将它移动到一个资源,这是相同的,当然我们假设 Child 将永远是一个按钮:

<Style x:Key="ButtonBorder" TargetType="{x:Type Border}">
    <Style.Triggers>                
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Child.IsPressed}" Value="True">
            <Setter Property="Background" Value="Blue"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

最好的方法是什么,或者我缺少什么?我可以看到,当 "Child" 用作内联样式时,智能感知颜色 Child 不同,我确信这意味着什么。从 resource-defined 样式假设 Child 的类型不好吗?

您可以为此使用附加属性。例如:

public static class Attached
{
    public static readonly DependencyProperty RelatedControlProperty = DependencyProperty.RegisterAttached(
        "RelatedControl", typeof(UIElement), typeof(Attached));

    public static void SetRelatedControl (DependencyObject element, UIElement value)
    {
        element.SetValue(RelatedControlProperty, value);
    }

    public static UIElement GetRelatedControl (DependencyObject element)
    {
        return (UIElement)element.GetValue(RelatedControlProperty);
    }
}

这个属性没有逻辑,它只是用于"connecting"控制你喜欢的任何方式。

在样式中,您阅读了您控件的附件属性:

<Style x:Key="ButtonBorder" TargetType="{x:Type Border}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding 
                RelativeSource={RelativeSource Self}, 
                Path=(local:Attached.RelatedControl).IsPressed}" Value="True">
            <Setter Property="Background" Value="Blue"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

并且在创建控件时,将附加的 属性 设置为子控件:

<Border Name="parentBorder" Padding="20" Style="{StaticResource ButtonBorder}"
        local:Attached.RelatedControl="{x:Reference childButton}">
    <Button Name="childButton" Content="Don't Push Me Bro"/>
</Border>

我不建议使用 Child 属性,因为它会使您的设计变得脆弱。您假设一个控件将只包含一个控件并且仅直接包含。如果将按钮放在边框内的网格内,它将停止工作。从逻辑子关系中分离样式关系将使样式更加灵活。

如果您真正想要的是仅对直接包含按钮的边框使用边框样式,也许您应该只覆盖按钮的模板。