【问题标题】:Why does assigning a background color to a control override the style trigger?为什么为控件分配背景颜色会覆盖样式触发器?
【发布时间】:2014-07-16 16:38:07
【问题描述】:

我有一个带有标签的简单 WPF 窗口。窗口中有一个默认样式,当鼠标悬停在标签上时,它会将标签背景更改为红色。很简单。

只要我不在任何地方将标签颜色设置/修改为任何东西,它就可以工作。

  • 如果我在后面的代码中设置标签背景(通过下面代码中的“设置标签背景”按钮),样式触发器将停止工作
  • 如果我在 XAML 中设置标签背景(未显示,但可以轻松编辑),则样式不起作用。
  • 如果在后面的代码中设置标签颜色后,我尝试将背景恢复为原来的状态(无论是空的还是透明的),触发器就会从工作变为不工作。

我不明白为什么设置背景似乎会覆盖样式。

无论我为标签设置什么背景,我更愿意这样做是保持样式处于活动状态 - 如果我将鼠标移到上方,它应该将颜色更改为红色,无论我是否将其设置为蓝色或其他任何东西。如果我必须在后面的代码中创建触发器,我可以。

相反,似乎只是通过为标签分配背景颜色,我覆盖了样式。

这是 XAML:

    <Grid Background="Black">   
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <Button Grid.Column="0" Grid.Row="0" Margin="10,10,10,10" Height="75" Click="Button_Set_Click">Set Label Background</Button>
    <Button Grid.Column="0" Grid.Row="1" Margin="10,10,10,10" Height="75" Click="Button_Clear_Click">Clear Label Background</Button>
    <Label Name="TestLabel" Grid.Row="2"  Margin="10,10,10,10" BorderBrush="Gray" BorderThickness="5"></Label>
    </Grid>

下面是代码:

public partial class WpfProblems : Window
{
    public WpfProblems()
    {
        InitializeComponent();
    }

    private void Button_Clear_Click(object sender, RoutedEventArgs e)
    {
        // revert the label background color - I've tried setting to null, transparent also
        // but the trigger never comes back. 
        TestLabel.Background = (Brush)new BrushConverter().ConvertFrom("#00FFFFFF");            
    }

    private void Button_Set_Click(object sender, RoutedEventArgs e)
    {
        // Set the label background color
        TestLabel.Background = Brushes.Blue;
    }
}

【问题讨论】:

    标签: wpf


    【解决方案1】:

    通过为您的 Label 分配颜色,您将覆盖其 Color 属性(之前拥有绑定)。因此,最终您通过在代码后面或 xaml 中直接分配颜色来破坏绑定。

    要解决问题,您必须在标签样式中指定默认颜色,以便在触发条件完成后保留颜色。

    假设您的样式如下所示。请注意我是如何为触发器部分上方的标签设置默认颜色的。

    <Style TargetType="{x:Type Label}">
    <Setter Property="Background" Value="Blue"/>
    <Style.Triggers>
    <Trigger Property="IsMouseOver" Value="true">
    <Setter Property="Background" Value="Red/>
    </Trigger>
    </Style.Triggers>
    </Style>
    

    编辑 -

    由于您使用的是代码隐藏文件,我认为您可以使用 DependencyProperty 来控制标签的颜色。我在一个测试应用程序上试过这个,它可以工作。

    如下创建一个dependencyProperty。请注意默认颜色为蓝色,与您的测试应用程序一样。

    public Brush BackgroundColor
            {
                get { return (Brush)GetValue(BackgroundColorProperty); }
                set { SetValue(BackgroundColorProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for BackgroundColor.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty BackgroundColorProperty =
                DependencyProperty.Register("BackgroundColor", typeof(Brush), typeof(MainWindow), new PropertyMetadata(Brushes.Blue));
    

    现在您的按钮点击事件将变为

    private void Button_Click(object sender, RoutedEventArgs e)
            {
                BackgroundColor = Brushes.Yellow;
            }
    
            private void Button_Click_1(object sender, RoutedEventArgs e)
            {
                BackgroundColor = Brushes.Blue;
            }
    

    在主窗口(或您的用户控件)中,我为标签定义了以下样式

    <Window.Resources>
            <Style TargetType="{x:Type Label}">
                <Setter Property="Background" Value="{Binding BackgroundColor}"/>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Background" Value="Red"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
    
    
    
    <Grid Background="Black">
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <Button Grid.Column="0" Grid.Row="0" Margin="10,10,10,10" Height="75" Click="Button_Click">Set Label Background</Button>
                <Button Grid.Column="0" Grid.Row="1" Margin="10,10,10,10" Height="75" Click="Button_Click_1">Clear Label Background</Button>
                <Label Name="TestLabel"  Grid.Row="2"  Margin="10,10,10,10" BorderBrush="Gray" BorderThickness="5"></Label>
            </Grid>
    

    我使用的是你发布的同一个网格

    确保您在后面的代码中正确设置控件的数据上下文以使其正常工作。现在,即使单击任何按钮,原始样式也会保留。

    让我知道这是否有效。

    【讨论】:

    • 请参阅Dependency Property Value Precedence,了解您“打破绑定”的原因。
    • 这有帮助。是否有可能拥有 N 种不同的风格,然后在后面的代码中选择一种?或者,我可能只是放弃在 XAML IsMouseOver 触发器上设置颜色的想法,并使用鼠标进入/鼠标退出来处理代码中的所有内容。
    • 如果您想在后面的代码中分配样式,您可以随时使用 FindResource 从资源字典中查找样式并将其手动分配给标签。我不会推荐它,但你可以做到。语法 - TestLabel.Style = (Style)FindResource("Style2");
    • 请查看我使用 DependencyProperty 进行的编辑,如果它解决了您的问题,请告诉我
    【解决方案2】:

    DependencyPropertys 可以从许多不同的来源设置。例如,可以在Styles、Animations、Triggers 等中设置它们。因此,Microsoft 确定其中一些更新源比其他更新源更重要,因此应该优先于其他更新源。

    例如,Trigger 中的 Setter 应该比普通的 Style Setter 具有更高的优先级,因为否则,Triggers 将不起作用。

    无论我为标签设置什么背景,我更希望这样做是保持样式处于活动状态

    显然,根据您设置Background 的方式,这可能不起作用...代码中的简单属性设置将始终覆盖Style 中设置的属性。

    要了解更多信息,请阅读 MSDN 上的Dependency Property Value Precedence 页面。

    【讨论】:

      猜你喜欢
      • 2011-03-15
      • 2015-11-16
      • 1970-01-01
      • 2017-04-29
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      • 2018-01-25
      • 1970-01-01
      相关资源
      最近更新 更多