从DataTrigger内部更改样式

Ben*_*jol 4 wpf xaml

正如WPF经常发生的那样,我可能会以错误的方式处理事情,但我有以下情况:

我想根据DataTrigger应用样式,但是你不能在Style中更改Style:

<Button>
   <Button.Style>
      <Style BasedOn="SomeStyle">
         <Style.Triggers>
            <DataTrigger ...>
               <Setter Property="Style" Value="OtherStyle" /> <---- NO CAN DO
Run Code Online (Sandbox Code Playgroud)

逻辑真的,但我想避免的是重复相同的 setter,只是因为我的触发条件改变了:

<Button>
   <Button.Style>
      <Style BasedOn="SomeStyle">
         <Style.Triggers>
            <DataTrigger Binding="{Binding X}" Value="Condition1">
               <Setter Property="A" Value="1" /> 
               <Setter Property="B" Value="1" /> 
               <etc...>
(...)

<Button>
   <Button.Style>
      <Style BasedOn="SomeStyle">
         <Style.Triggers>
            <DataTrigger Binding="{Binding X}" Value="Condition2">
               <Setter Property="A" Value="1" /> 
               <Setter Property="B" Value="1" /> 
               <etc...>
Run Code Online (Sandbox Code Playgroud)

是否还有其他内容可以放置DataTrigger,从而允许我从里面改变样式?或者另一种方式:避免重复样式信息?

pus*_*raj 12

下面是一个如何根据数据触发器更改元素样式的示例

<StackPanel>
    <Control Focusable="False">
        <Control.Template>
            <ControlTemplate>
                <!--resources-->
                <ControlTemplate.Resources>
                    <Style TargetType="Button" x:Key="primary">
                        <Setter Property="Content" Value="Primary style"/>
                    </Style>
                    <Style TargetType="Button" x:Key="secondry">
                        <Setter Property="Content" Value="Secondry style"/>
                    </Style>
                </ControlTemplate.Resources>
                <!--content-->
                <Button Style="{StaticResource primary}" x:Name="button"/>
                <!--triggers-->
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}" Value="true">
                        <Setter TargetName="button" Property="Style" Value="{StaticResource secondry}"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding IsKeyboardFocusWithin,RelativeSource={RelativeSource Self}}" Value="true">
                        <Setter TargetName="button" Property="Style" Value="{StaticResource secondry}"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Control.Template>
    </Control>
    <Button Content="A normal button"/>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

在这个例子中Control是一个包装元素,它将在它的控件模板中托管所需的元素.如果您希望按名称访问它,则必须位于控件模板中.在控件模板的触发器中定义了一组数据触发器,它将根据需要在所需元素(按钮)上应用样式.

我没有找到避免重复setter的方法,也许交换/应用样式的能力可能会帮助你实现同样的目标.

如果您不想使用控件模板方法,则可以在元素中使用附加属性或未使用的Tag属性.在这个例子中,我们将利用双向绑定来实现相同的功能

<StackPanel>
    <Grid>
        <!--content-->
        <Button Style="{Binding Tag,RelativeSource={RelativeSource FindAncestor,AncestorType=Grid}}"/>
        <Grid.Style>
            <Style TargetType="Grid">
                <!--resources-->
                <Style.Resources>
                    <Style TargetType="Button" x:Key="primary">
                        <Setter Property="Content" Value="Primary style"/>
                    </Style>
                    <Style TargetType="Button" x:Key="secondry">
                        <Setter Property="Content" Value="Secondry style"/>
                    </Style>
                </Style.Resources>
                <Setter Property="Tag" Value="{StaticResource primary}"/>
                <!--triggers-->
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}" Value="true">
                        <Setter Property="Tag" Value="{StaticResource secondry}"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding IsKeyboardFocusWithin,RelativeSource={RelativeSource Self}}" Value="true">
                        <Setter Property="Tag" Value="{StaticResource secondry}"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>
    </Grid>
    <Button Content="A normal button"/>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

尝试一下,看看这是否有助于您实现所需.

  • 勉强的投票。这两种解决方案看起来都很难看,尽管我知道那不是你的错:( (2认同)