Фон кнопки с отключенным WPF

Я пытаюсь изменить стиль кнопки, когда она отключена:

    <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>

и моя кнопка:

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

Но почему-то этот стиль не применяется к кнопке:

enter image description here

Как я могу применить этот стиль к моей кнопке? И могу ли я сделать это без переопределения шаблона кнопки только со стилями?

Ответ 1

Могу ли я сделать это без переопределения шаблона кнопки только со стилями?

Я думаю, что нет, потому что элементы управления в Windows имеют значения по умолчанию Styles и ControlTemplates, а в каждой версии Windows они разные. Кроме того, стили - это всего лишь множество настроек, обычно стиль не меняет/добавляет поведение к управлению, которое отвечает за это ControlTemplate.

Note: Стиль - это набор сеттеров, например: установите фон, размер и т.д. ControlTemplate - это форма, в которой будут отображаться все эти параметры.

В этой ситуации я рекомендую всем вам изменить ControlTemplate, где возможно иметь такое же поведение, как и просмотр, независимо от версии системы.

В этом случае попробуйте выполнить 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>

Ответ 2

Странно то, что он "работает", когда я запускаю его, отчасти, и это, скорее всего, шаблон кнопки на самом деле. Вот цельный шаблон кнопок.

<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>

Как вы видите, в шаблоне управления кнопки много чего происходит. В примере используются следующие SolidColorBrushes, когда ctl отключен.

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

Вы можете либо изменить их (в рамках вашего пользовательского контроля, приложения), либо переписать шаблон управления, как предложено Дэниелом Уордом.

Вы можете сбросить шаблон по умолчанию любого элемента управления, щелкнув его правой кнопкой мыши в редакторе пользовательского интерфейса, отредактировать шаблон → Создать копию... С помощью сочетания, кода или дизассемблирования:)

Надеюсь, что это поможет!

Приветствия

Стиан

Ответ 3

Кажется, что единственный способ сделать это - удалить тему chrome из кнопки. Обратите внимание, что это удалит анимацию зависания/клика, а также градиент кнопки в Windows 7, если вы создаете для этого.

К сожалению, Microsoft решила, что отключение кнопки должно дать фону жестко закодированное значение из частного свойства в коде кода chrome, которое означает, что вы не можете изменить его через XAML. Эта ссылка описывает проблему:

Шаблон управления для Button использует ButtonChrome, который имеет частное свойство ButtonOverlay, которое, когда Button имеет IsEnabled, установленное на False, устанавливает Background в new SolidColorBrush(Color.FromRgb(0xf4, 0xf4, 0xf4)) (или RGB 244,244,244), который является серым, который вы видите. Вы не можете изменить это.

Что вы можете сделать, так это создать новый шаблон управления для кнопки (yay), заменив элемент Themes:ButtonChrome на элемент Border, который вы можете изменить Background.

Возможно, он не работает в дизайне, но работает, когда вы его запускаете.

Итак, например, для вашего, это может выглядеть примерно так:

<!-- 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>

Ответ 4

Мое решение немного проще, но оно не позволяет использовать Transparent цвет фона для отключенной кнопки, и вы также не можете изменить BorderBrush. Я использую TextBlock в качестве содержимого кнопки и меняю цвет этого фона TextBlock когда он отключен.

Моя кнопка написана так:

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

И MyButtonContentStyle записывается так:

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

Это сработало как шарм для нас.

Ответ 5

Может быть, уже поздно, но есть встроенное свойство, предоставляемое WPF:

IsHitTestVisible="False"

Любое движение мыши не распознается с помощью вышеуказанного элемента управления, поэтому отключается элемент управления без изменения его фактического внешнего вида.