web-dev-qa-db-fra.com

Arrière-plan du bouton WPF désactivé

J'essaie de changer le style du bouton lorsqu'il est désactivé:

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

et mon bouton:

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

Mais pour une raison quelconque, ce style n'est pas appliqué au bouton:

enter image description here

Comment puis-je appliquer ce style à mon bouton? Et puis-je le faire sans remplacer le modèle de bouton uniquement avec des styles?

24
Junior222

Puis-je le faire sans remplacer le modèle de bouton uniquement avec des styles?

Je ne pense pas, parce que les contrôles dans Windows ont un Styles et ControlTemplates et par défaut dans chaque version de Windows, ils sont différents . De plus, les styles - c'est juste beaucoup de paramètres, généralement le style ne change pas/n'ajoute pas de comportement au contrôle, qui est responsable de ce ControlTemplate.

Note: le Style c'est un ensemble de setters, par exemple: définissez l'arrière-plan, la taille, etc. Le ControlTemplate est la forme, dans laquelle tous ces paramètres apparaîtront.

Dans cette situation, je vous recommande à tous de changer le ControlTemplate, où il est possible d'avoir le même comportement aka view, quelle que soit la version du système.

Dans ce cas, essayez ceci 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>
25
Anatoliy Nikolaev

La chose étrange est que cela "fonctionne" quand je l'exécute, enfin en partie, et c'est probablement le modèle du bouton en fait. Voici un modèle complet de boutons.

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

Comme vous pouvez le voir, il se passe beaucoup de choses dans le modèle de contrôle du bouton. Dans l'exemple, les SolidColorBrushes suivants sont utilisés lorsque le ctl est désactivé.

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

Vous pouvez soit les modifier (dans le cadre de votre contrôle utilisateur, application), soit réécrire le modèle de contrôle comme suggéré par Daniel Ward.

Vous pouvez vider le modèle par défaut de n'importe quel contrôle en cliquant dessus avec le bouton droit dans l'éditeur d'interface utilisateur, Modifier le modèle -> Créer une copie ... Par mélange, code ou désassemblage :)

J'espère que cela aide!

À votre santé

Stian

8
Stígandr

Il semble que la seule façon de procéder consiste à supprimer le thème chrome du bouton. Notez que cela supprimera également les animations de survol/clic) comme le gradient du bouton sur Windows 7, si vous construisez pour cela.

Malheureusement, Microsoft a décidé que la désactivation d'un bouton devrait donner à l'arrière-plan une valeur codée en dur à partir d'une propriété privée dans le code chrome , ce qui signifie que vous ne pouvez pas changez-le via le XAML. Ce lien décrit le problème:

Le modèle de contrôle pour Button utilise ButtonChrome, qui possède une propriété privée appelée ButtonOverlay, qui, lorsque Button a IsEnabled défini sur False, définit Background sur new SolidColorBrush(Color.FromRgb(0xf4, 0xf4, 0xf4)) (ou RVB 244, 244, 244), qui est le gris que vous voyez. Tu ne peux pas changer ça.

Ce que vous pouvez faire est de créer un nouveau modèle de contrôle pour le bouton (yay), en remplaçant le Themes:ButtonChrome élément avec un élément Border, dont vous pouvez changer le Background de.

Il ne semble pas fonctionner en mode Création, mais il fonctionne lorsque vous l'exécutez.

Ainsi, par exemple, pour le vôtre, cela pourrait ressembler à quelque chose comme:

<!-- 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>
2
Daniel Ward

Peut-être en retard sur celui-ci mais il y a une propriété intégrée fournie par WPF:

IsHitTestVisible="False"

Tout type de mouvement de la souris n'est pas détectable à l'aide de ce qui précède sur un contrôle, désactivant ainsi un contrôle sans changer son apparence réelle.

1
Ishan Khanna

Ma solution est un peu plus simple mais elle ne permet pas d'utiliser une couleur d'arrière-plan Transparent pour un bouton désactivé et vous ne pouvez pas non plus changer la BorderBrush. Ce que je fais, c'est utiliser un TextBlock comme contenu du bouton et changer la couleur de cet arrière-plan TextBlock quand il est désactivé.

Mon bouton est écrit comme ceci:

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

Et MyButtonContentStyle est écrit comme ceci:

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

Cela a fonctionné comme un charme pour nous.

1
Mohammed Larabi