WPF Disabled button's background

2020-02-10 11:06发布

I try to change button's style when it is disabled:

    <Style TargetType="Button" x:Key="MyButton2">
        <Setter Property="Background" Value="MediumAquamarine" />
        <Setter Property="Foreground" Value="MediumBlue" />

        <Style.Triggers>
            <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Background" Value="Green"/>
                <Setter Property="Foreground" Value="DeepPink"/>
            </Trigger>
        </Style.Triggers>

    </Style>

and my button:

<Button Style="{StaticResource MyButton2}" Content="My text" Width="100" Height="30" IsEnabled="False" />    

But for some reason This style is not applied to the button:

enter image description here

How can i apply this style to my button? And can i do it without overriding button's template only with styles?

标签: wpf xaml styles
5条回答
地球回转人心会变
2楼-- · 2020-02-10 11:44

Can I do it without overriding button's template only with styles?

I think not, because the Controls in the Windows has a default Styles and ControlTemplates and in each version of Windows they are different. In addition, the styles - it's just a lot of settings, usually the style does not change/add behavior to control, which is responsible for this ControlTemplate.

Note: the Style it is a set of setters, for example: set the background, size, etc. The ControlTemplate is the form, in which all of these settings will appear.

In this situation, I recommend you all to change the ControlTemplate, where it is possible to have the same behavior aka view, regardless of the version of the system.

In this case, try this Style:

<Window.Resources>
    <Style TargetType="Button" x:Key="MyButton2">
        <Setter Property="OverridesDefaultStyle" Value="True" />
        <Setter Property="Background" Value="MediumAquamarine" />
        <Setter Property="Foreground" Value="MediumBlue" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid Background="{TemplateBinding Background}">
                        <ContentPresenter x:Name="MyContentPresenter" 
                                          Content="{TemplateBinding Content}"
                                          HorizontalAlignment="Center" 
                                          VerticalAlignment="Center" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Background" Value="Green"/>
                <Setter Property="Foreground" Value="DeepPink"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" 
            IsEnabled="False"
            HorizontalAlignment="Left" 
            VerticalAlignment="Top" 
            Width="75" 
            Style="{StaticResource MyButton2}"
            Click="Button_Click"/>
</Grid>
查看更多
Emotional °昔
3楼-- · 2020-02-10 11:45

The odd thing is that it "works" when i run it, well partly, and this is likely to the template of the button actually. Here is a buttons entire template.

<Style x:Key="FocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
    <Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
    <Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                    <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsDefaulted" Value="true">
                        <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>
                        <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="true">
                        <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
                        <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
                        <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
                        <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

As you can see there is alot of things going on in the control template of the button. In example the following SolidColorBrushes are used when the ctl is disabled.

<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>

You can either change these (in scope of your usercontrol, app), or you can rewrite the control template as Suggested by Daniel Ward.

You may dump the default template of any control by right clicking it in the UI Editor, Edit Template -> Create a copy... Through blend, code or disassembling :)

Hope it helps!

Cheers

Stian

查看更多
爷的心禁止访问
4楼-- · 2020-02-10 11:55

Might be late on this one but there is an in built property provided by WPF:

IsHitTestVisible="False"

Any kind of mouse movement is not detectable using the above on a control thus disabling a control without changing its actual look and feel.

查看更多
▲ chillily
5楼-- · 2020-02-10 11:59

It seems that the only way to do this is to remove the chrome theme from the button. Note that this will remove the hovering/clicking animations, as well as the button's gradient on Windows 7, if you're building for that.

Unfortunately, Microsoft decided that disabling a button should give the background a hardcoded value from a private property in the chrome theme's code-behind, which means that you can't change it through the XAML. That link describes the problem:

The control template for Button uses ButtonChrome, which has a private property called ButtonOverlay, which, when the Button has IsEnabled set to False, sets the Background to new SolidColorBrush(Color.FromRgb(0xf4, 0xf4, 0xf4)) (or RGB 244,244,244), which is the grey you see. You can't change that.

What you can do is create a new control template for the button (yay), replacing the Themes:ButtonChrome element with a Border element, which you are able to change the Background of.

It may not appear to work in design view, but it works when you run it.

So, for instance, for yours, it might look something like:

<!-- Default button focus visual -->
<Style x:Key="ButtonFocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
    <Setter Property="Background" Value="MediumAquamarine"/>
    <Setter Property="Foreground" Value="MediumBlue"/>
    <Setter Property="BorderBrush" Value="Blue"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="DeepPink"/>
                        <Setter Property="Background" Value="Green"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
查看更多
Anthone
6楼-- · 2020-02-10 12:04

My solution is a bit easier but it does not allow to use a Transparent background color for a disabled button and you cannot change the BorderBrush either. What I do is using a TextBlock as a content of the button and change the color of this TextBlock background when it's disabled.

My button is written like this:

<Button>
    <TextBlock Text="Click me!" Style="{StaticResource MyButtonContentStyle}" />
</Button>

And MyButtonContentStyle is written like this:

<Style x:Key="MyButtonContentStyle" TargetType="TextBlock">
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Background" Value="White" />
        </Trigger>
    </Style.Triggers>
</Style>

It worked like a charm for us.

查看更多
登录 后发表回答