.net 如何从资源定义的样式将DataTrigger绑定到子属性?

.net 如何从资源定义的样式将DataTrigger绑定到子属性?,.net,wpf,binding,styles,datatrigger,.net,Wpf,Binding,Styles,Datatrigger,如何根据子属性中的更改设置元素的样式?我会接受一种不同的方法,但理想的结果是只要子属性(IsPressed)为true,父属性就以某种方式设置 如果我们使用内嵌样式设置一个命名项的样式,我们可以简单地使用ElementName来识别我们的子项,但我们甚至可以更不具体地使用child.IsPressed: <Border Name="parentBorder" Padding="20"> <Button Name="childButton" Content="Don't

如何根据子属性中的更改设置元素的样式?我会接受一种不同的方法,但理想的结果是只要子属性(IsPressed)为true,父属性就以某种方式设置

如果我们使用内嵌样式设置一个命名项的样式,我们可以简单地使用ElementName来识别我们的子项,但我们甚至可以更不具体地使用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>

但由于我想重用样式和样式多个边框,我想将其移动到一个资源,这是相同的,当然我们假设子对象始终是按钮:

<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”用作内联样式时,intellisense会给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);
    }
}
此属性没有逻辑,它只是用于以任何方式“连接”控件

在样式中,可以读取控件的附加属性:

<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
属性,因为它会使您的设计变得脆弱。假设一个控件只包含一个控件,并且只直接包含一个控件。如果你把一个按钮放在边框内的网格内,它将停止工作。将样式关系与逻辑子关系分离将使样式更加灵活


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

Aha-那么我是否正确地认为它只是对Child了解不够,这是告诉它应该使用哪种类型的方式?对于附加属性,它仍然没有从样式中指定,但我认为这是问题的一部分。我还假设,如果我在孩子不是按钮(或没有按下按钮)时应用样式,它会尝试失败。@JoshSutterfield如果找不到属性,绑定将自动失败,触发器将永远不会触发。如果您想绝对确保只有按钮的
IsPressed
用于绑定,而没有其他用途,可以使用以下表达式:
(本地:Attached.RelatedControl)。(ButtonBase.IsPressed)
。如果您想支持多种类型的控件,可以使用
PriorityBinding
并为每个属性列出多个绑定。令我惊讶的是,它无法在存在属性的情况下找到该属性。从静态资源中使用{Binding ElementName=childButton,Path=IsPressed}的同样脆弱的方法碰巧可以工作。啊,是的,这将是脆弱性与可读性之间的折衷&所有内容都完全在XAML中,但我很高兴知道更健壮的方法。@JoshSutterfield好吧,
Child
属性不是依赖性属性,所以它的问题并不奇怪。这是有意义的,可以做到。