Come si cambia lo sfondo per un Button MouseOver in WPF?


93

Ho un pulsante sulla mia pagina con questo XAML:

<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Bottom" 
    Width="50" Height="50" HorizontalContentAlignment="Left" 
    BorderBrush="{x:Null}" Foreground="{x:Null}" Margin="50,0,0,0">
    <Button.Style>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Green"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Red"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

Ma quando metto il mouse sul mio pulsante, lo sfondo del pulsante cambia allo sfondo grigio predefinito di Windows.
Qual è il problema?

Questa è l'immagine del pulsante prima e dopo il passaggio del mouse:
Prima:
Prima
Dopo:
Dopo


Ma devi avviare l'immagine Forward-48.pnge attivare IsMouseOver per cambiarlo per lo stesso Forward-48.png. Sto provando a utilizzare il tuo codice con immagini diverse e ho funzionato bene.
Anatoliy Nikolaev

1
@anatoliy: non funziona.
Sepehr Mohammadi

Dopo è il tuo colore predefinito? Altrove non modifichi / non imposti lo sfondo di un pulsante? Ho il tuo codice che funziona bene.
Anatoliy Nikolaev

Risposte:


173

Per rimuovere il MouseOvercomportamento predefinito su Buttonsarà necessario modificare il file ControlTemplate. Cambiare la tua Styledefinizione come segue dovrebbe fare il trucco:

<Style TargetType="{x:Type Button}">
    <Setter Property="Background" Value="Green"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Background="{TemplateBinding Background}" BorderBrush="Black" BorderThickness="1">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Red"/>
        </Trigger>
    </Style.Triggers>
</Style>

EDIT: sono passati alcuni anni, ma in realtà sei in grado di impostare il pennello del bordo all'interno del bordo che si trova lì. Idk se fosse stato sottolineato ma non sembra che fosse ...


1
Funziona, tuttavia il pulsante Bordi scomparirà! Ho dovuto inserire un elemento <Border BorderBrush = "DarkGray" BorderThickness = "1"> attorno al pulsante.
Venugopal M

4
@CF la ragione di ciò è che lo stile Button standard ha trigger all'interno ControlTemplate, quindi sovrascrivono i Styletrigger OP .
torvin

1
@torvin Sembra così al contrario! Perché un trigger definito dall'utente dovrebbe essere sovrascritto da quelli predefiniti? Capisco la gerarchia, ControlTemplate è al di sopra di Style, ma non capisco perché debba essere così difficile sovrascrivere impostazioni di base come queste.
Fuselight

@ Fuselight, il grilletto all'interno di ControlTemplatefondamentalmente dice 'Dipingi il bordo in base al Backgroundcolore. E se il mouse è sopra il pulsante, dipingi invece quel bordo di questo colore ', mentre nello stile hai accesso solo al Backgroundcolore e non al colore del bordo sottostante. Vedo il tuo punto però, lo stile WPF lascia molto a desiderare ...
torvin

Questo ha l'ulteriore vantaggio di rimuovere la casella blu che appare al rollover, quando si utilizza un'immagine con uno sfondo trasparente. Nel mio caso non volevo il confine, quindi imposta BorderThickness su 0.
Chuck Savage

20

Tutte le risposte finora implicano la sostituzione completa del comportamento predefinito del pulsante con qualcos'altro. Tuttavia, IMHO è utile e importante capire che è possibile cambiare solo la parte che ti interessa , modificando il modello predefinito esistente per un elemento XAML.

In caso di gestione dell'effetto al passaggio del mouse su un pulsante WPF, la modifica dell'aspetto in un Buttonelemento WPF è causata da uno Triggerstile predefinito per il Button, che si basa sulla IsMouseOverproprietà e imposta le proprietà Backgrounde dell'elemento di BorderBrushprimo livello Bordernel modello di controllo. Lo Buttonsfondo dell'elemento si trova sotto lo Bordersfondo dell'elemento, quindi la modifica della Button.Backgroundproprietà non impedisce la visualizzazione dell'effetto al passaggio del mouse.

Con un po 'di sforzo, potresti ignorare questo comportamento con il tuo setter, ma poiché l'elemento che devi influenzare si trova nel modello e non è direttamente accessibile nel tuo XAML, quell'approccio sarebbe difficile e IMHO eccessivamente complesso.

Un'altra opzione potrebbe essere quella di utilizzare la grafica come Contentper il Buttonpiuttosto che come Background. Se hai bisogno di contenuto aggiuntivo sulla grafica, puoi combinarli con un Gridoggetto di primo livello nel contenuto.

Tuttavia, se vuoi letteralmente disabilitare completamente l'effetto hover (invece di nasconderlo), puoi usare la finestra di progettazione XAML di Visual Studio:

  1. Durante la modifica del codice XAML, seleziona la scheda "Progettazione" .
  2. Nella scheda "Design" , trova il pulsante per il quale desideri disattivare l'effetto.
  3. Fare clic con il pulsante destro del mouse e scegliere "Modifica modello / Modifica una copia ..." . Selezionare nel prompt che si ottiene dove si desidera posizionare la nuova risorsa modello. Questo sembrerà non fare nulla, ma in realtà il Designer avrà aggiunto nuove risorse dove le hai detto e cambiato il tuo elemento pulsante per fare riferimento allo stile che utilizza quelle risorse come modello di pulsante.
  4. Ora puoi modificare quello stile. La cosa più semplice è eliminare o commentare (es. Ctrl+ E, C) L' <Trigger Property="IsMouseOver" Value="true">...</Trigger>elemento. Ovviamente, a quel punto puoi apportare qualsiasi modifica al modello che desideri.

Quando hai finito, lo stile del pulsante sarà simile a questo:

<p: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>
</p: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"/>
<p: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>
</p:Style>

(Nota: puoi omettere le p:qualifiche dello spazio dei nomi XML nel codice effettivo ... Le fornisco qui solo perché il formattatore di codice XML di Stack Overflow viene confuso da <Style/>elementi che non hanno un nome completo con lo spazio dei nomi XML.)

Se desideri applicare lo stesso stile ad altri pulsanti, puoi semplicemente fare clic con il pulsante destro del mouse su di essi e scegliere "Modifica modello / Applica risorsa" e selezionare lo stile appena aggiunto per il primo pulsante. Puoi persino impostare tale stile come stile predefinito per tutti i pulsanti, utilizzando le normali tecniche per applicare uno stile predefinito agli elementi in XAML.


5
Grazie mille. Questa è l'unica risposta tollerabile qui
Jared Beach,

13

Questo ha funzionato bene per me.

Stile pulsante

<Style x:Key="TransparentStyle" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border>
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="DarkGoldenrod"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <Grid Background="Transparent">
                        <ContentPresenter></ContentPresenter>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Pulsante

<Button Style="{StaticResource TransparentStyle}" VerticalAlignment="Top" HorizontalAlignment="Right" Width="25" Height="25"
        Command="{Binding CloseWindow}">
    <Button.Content >
        <Grid Margin="0 0 0 0">
            <Path Data="M0,7 L10,17 M0,17 L10,7" Stroke="Blue" StrokeThickness="2" HorizontalAlignment="Center" Stretch="None" />
        </Grid>
    </Button.Content>
</Button>

Appunti

  • Il pulsante mostra una piccola croce blu, molto simile a quella usata per chiudere una finestra.
  • Impostando lo sfondo della griglia su "Trasparente", si aggiunge un punto più alto, il che significa che se il mouse è ovunque sopra il pulsante, allora funzionerà. Ometti questo tag e il pulsante si illuminerà solo se il mouse si trova su una delle linee vettoriali nell'icona (questo non è molto utilizzabile).

1
Questa è un'ottima risposta, ma che ne dici di cambiare il Strokecolore anche al passaggio del mouse Border, senza che passi solo sopra Path?
Nateous

1
Questa x:Key="TransparentStyle"parte e l'utilizzo sono stati importanti per me per arrivarci ... Grazie!
nrod

6

Voglio solo condividere il mio stile di pulsante dal mio ResourceDictionary che ho usato. Puoi cambiare liberamente lo sfondo di onHover nei trigger di stile. " ColorAnimation To = * il BG desiderato (ad esempio # FFCEF7A0)". Il pulsante BG tornerà automaticamente al suo BG originale anche dopo lo stato MouseOver. Puoi persino impostare la velocità della transizione.

Dizionario delle risorse

<Style x:Key="Flat_Button" TargetType="{x:Type Button}">
    <Setter Property="Width" Value="100"/>
    <Setter Property="Height" Value="50"/>
    <Setter Property="Margin" Value="2"/>
    <Setter Property="FontFamily" Value="Arial Narrow"/>
    <Setter Property="FontSize" Value="12px"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="Foreground">
        <Setter.Value>
            <SolidColorBrush Opacity="1" Color="White"/>
        </Setter.Value>
    </Setter>
    <Setter Property="Background" >
        <Setter.Value>
            <SolidColorBrush Opacity="1" Color="#28C2FF" />
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">

                <Border x:Name="border"
                         SnapsToDevicePixels="True"
                         BorderThickness="1"
                         Padding="4,2"
                         BorderBrush="Gray"
                         CornerRadius="3"
                         Background="{TemplateBinding Background}">
                    <Grid>
                        <ContentPresenter 
                        Margin="2"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        RecognizesAccessKey="True" />

                    </Grid>
                </Border>

            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="true">
            <Trigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation To="#D2F898"
                                        Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" 
                                        FillBehavior="HoldEnd" Duration="0:0:0.25" AutoReverse="False" RepeatBehavior="1x"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>

            <Trigger.ExitActions>
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation
                                            Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" 
                                            FillBehavior="HoldEnd" Duration="0:0:0.25" AutoReverse="False" RepeatBehavior="1x"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.ExitActions>

        </Trigger>


    </Style.Triggers>
</Style>

tutto quello che devi fare è chiamare lo stile.

Esempio di implementazione

<Button Style="{StaticResource Flat_Button}" Height="Auto"Width="Auto">  
     <StackPanel>
     <TextBlock Text="SAVE" FontFamily="Arial" FontSize="10.667"/>
     </StackPanel>
</Button>

2

Una risposta leggermente più difficile che utilizza ControlTemplate e ha un effetto di animazione (adattato da https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/customizing-the-appearance-of-an-existing- controllo )

Nel dizionario delle risorse definisci un modello di controllo per il tuo pulsante come questo:

<ControlTemplate TargetType="Button" x:Key="testButtonTemplate2">
    <Border Name="RootElement">
        <Border.Background>
            <SolidColorBrush x:Name="BorderBrush" Color="Black"/>
        </Border.Background>

        <Grid Margin="4" >
            <Grid.Background>
                <SolidColorBrush x:Name="ButtonBackground" Color="Aquamarine"/>
            </Grid.Background>
            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="4,5,4,4"/>
        </Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Color" To="Red"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Pressed">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Color" To="Red"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Border>
</ControlTemplate>

nel tuo XAML puoi usare il modello sopra per il tuo pulsante come di seguito:

Definisci il tuo pulsante

<Button Template="{StaticResource testButtonTemplate2}" 
HorizontalAlignment="Center" VerticalAlignment="Center" 
Foreground="White">My button</Button>

Spero che sia d'aiuto


0

Per cambiare lo stile dei pulsanti

1 °: definire gli stili delle risorse

<Window.Resources>

    <Style x:Key="OvergroundIn" TargetType="Button">

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid Background="#FF16832F">
                        <ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">

                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="#FF06731F">
                                <ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>

            </Trigger>
        </Style.Triggers>

    </Style>

    <Style x:Key="OvergroundOut" TargetType="Button">

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid Background="#FFF35E5E">
                        <ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">

                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="#FFE34E4E">
                                <ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>

            </Trigger>
        </Style.Triggers>

    </Style>


</Window.Resources>

2 ° definire il codice del pulsante

                           <Border Grid.Column="2" BorderBrush="LightGray" BorderThickness="2" CornerRadius="3" Margin="2,2,2,2"  >
                                <Button Name="btnFichar" BorderThickness="0" Click="BtnFichar_Click">
                                    <Button.Content>
                                        <Grid>
                                            <TextBlock Margin="0,7,0,7" TextAlignment="Center">Fichar</TextBlock> 
                                        </Grid>
                                    </Button.Content>
                                </Button>
                            </Border>

3 ° codice dietro

    public void ShowStatus()
    {
        switch (((MainDto)this.DataContext).State)
        {
            case State.IN:
                this.btnFichar.BorderBrush = new SolidColorBrush(Color.FromRgb(243, 94, 94));
                this.btnFichar.Style = Resources["OvergroundIn"] as Style;
                this.btnFichar.Content = "Fichar Salida";
                break;

            case State.OUT:
                this.btnFichar.BorderBrush = new SolidColorBrush(Color.FromRgb(76, 106, 83));
                this.btnFichar.Style = Resources["OvergroundOut"] as Style;
                this.btnFichar.Content = "Fichar Entrada";
                break;

        }
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.