Wie ändere ich den Hintergrund für einen Button MouseOver in WPF?


92

Ich habe eine Schaltfläche auf meiner Seite mit dieser 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>

Wenn ich jedoch mit der Maus über meine Schaltfläche fahre, ändert sich der Hintergrund der Schaltfläche in den grauen Standardhintergrund von Windows.
Was ist das Problem?

Dies ist das Schaltflächenbild vor und nach dem Mouseover:
Vorher: Nachher
Vor
:
Nach dem


Sie müssen jedoch das Image starten Forward-48.pngund IsMouseOver auslösen, um es für dasselbe zu ändern Forward-48.png. Ich versuche, Ihren Code mit verschiedenen Bildern zu verwenden, und ich habe alle gut funktioniert.
Anatoliy Nikolaev

1
@anatoliy: Es funktioniert nicht.
Sepehr Mohammadi

Nach ist Ihre Standardfarbe? Wo sonst ändern oder setzen Sie keinen Schaltflächenhintergrund? Ich habe Ihren Code funktioniert gut.
Anatoliy Nikolaev

Antworten:


170

Um das Standardverhalten MouseOverauf dem zu entfernen, Buttonmüssen Sie das ändern ControlTemplate. Das Ändern Ihrer StyleDefinition in Folgendes sollte den Trick tun:

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

BEARBEITEN: Es ist ein paar Jahre zu spät, aber Sie können den Randpinsel tatsächlich innerhalb des Randes setzen, der sich dort befindet. Idk, wenn darauf hingewiesen wurde, aber es scheint nicht so, als ob es ...


1
Dies funktioniert, jedoch verschwindet der Button Borders! Musste ein <Border BorderBrush = "DarkGray" BorderThickness = "1"> Element um die Schaltfläche setzen.
Venugopal M

4
@CF Der Grund dafür ist, dass der Standard-Button-Stil Trigger enthält ControlTemplate, sodass die OP- StyleTrigger überschrieben werden .
Torvin

1
@torvin Das scheint so rückwärts! Warum sollte ein benutzerdefinierter Trigger standardmäßig überschrieben werden? Ich verstehe die Hierarchie, ControlTemplate steht über Style, aber ich verstehe nicht, warum es so schwierig sein muss, grundlegende Einstellungen wie diese zu überschreiben.
Fuselight

@Fuselight, der Auslöser im Inneren ControlTemplatesagt im Grunde ' Farbrand entsprechend der BackgroundFarbe malen . Und wenn sich die Maus über der Schaltfläche befindet, malen Sie stattdessen diesen Rand dieser Farbe, während Sie im Stil nur Zugriff auf die BackgroundFarbe und nicht auf die zugrunde liegende Rahmenfarbe haben. Ich sehe Sie jedoch zeigen, WPF Styling lässt zu wünschen übrig ...
Torvin

Dies hat den zusätzlichen Vorteil, dass das blaue Kästchen, das beim Rollover angezeigt wird, entfernt wird, wenn ein Bild mit transparentem Hintergrund verwendet wird. In meinem Fall wollte ich die Grenze nicht, also setze BorderThickness auf 0.
Chuck Savage

20

Bei allen bisherigen Antworten wird das Standardverhalten der Schaltflächen vollständig durch etwas anderes ersetzt. IMHO ist es jedoch nützlich und wichtig zu verstehen, dass es möglich ist, nur den Teil zu ändern, der Ihnen wichtig ist , indem Sie die vorhandene Standardvorlage für ein XAML-Element bearbeiten.

Wenn Sie sich mit dem Hover-Effekt auf einer WPF-Schaltfläche befassen, wird die Änderung des Erscheinungsbilds in einem WPF- ButtonElement durch a Triggerim Standardstil für das verursacht Button, der auf der IsMouseOverEigenschaft basiert und die Backgroundund BorderBrushEigenschaften des BorderElements der obersten Ebene festlegt in der Kontrollvorlage. Der ButtonHintergrund des BorderElements befindet sich unter dem Hintergrund des Elements. Wenn Sie also die Button.BackgroundEigenschaft ändern , wird der Hover-Effekt nicht sichtbar.

Mit etwas Aufwand könnten Sie dieses Verhalten mit Ihrem eigenen Setter überschreiben. Da sich das zu beeinflussende Element jedoch in der Vorlage befindet und in Ihrer eigenen XAML nicht direkt verfügbar ist, wäre dieser Ansatz schwierig und meiner Meinung nach zu komplex.

Eine andere Möglichkeit wäre, die Grafik eher Contentfür die Buttonals für die zu verwenden Background. Wenn Sie zusätzlichen Inhalt über die Grafik benötigen, können Sie diese mit einem GridObjekt der obersten Ebene im Inhalt kombinieren .

Wenn Sie den Hover-Effekt jedoch buchstäblich nur vollständig deaktivieren möchten (anstatt ihn nur auszublenden), können Sie den Visual Studio XAML Designer verwenden:

  1. Wählen Sie beim Bearbeiten Ihrer XAML die Registerkarte "Design" .
  2. In der „Design“ Registerkarte finden Sie die Schaltfläche für den Sie den Effekt deaktivieren möchten.
  3. Klicken Sie mit der rechten Maustaste auf diese Schaltfläche und wählen Sie "Vorlage bearbeiten / Kopie bearbeiten ..." . Wählen Sie in der Eingabeaufforderung aus, wo die neue Vorlagenressource platziert werden soll. Dies scheint nichts zu bewirken, aber tatsächlich hat der Designer neue Ressourcen hinzugefügt, wo Sie es gesagt haben, und Ihr Schaltflächenelement geändert, um auf den Stil zu verweisen, der diese Ressourcen als Schaltflächenvorlage verwendet.
  4. Jetzt können Sie diesen Stil bearbeiten. Am einfachsten ist es , das Element zu löschen oder auskommentieren (z. B. Ctrl+ E, C) <Trigger Property="IsMouseOver" Value="true">...</Trigger>. Natürlich können Sie an dieser Stelle jede gewünschte Änderung an der Vorlage vornehmen.

Wenn Sie fertig sind, sieht der Schaltflächenstil ungefähr so ​​aus:

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

(Hinweis: Sie können die p:XML-Namespace-Qualifikationen im eigentlichen Code weglassen. Ich stelle sie hier nur zur Verfügung, weil der XML-Code-Formatierer für Stapelüberlauf durch <Style/>Elemente verwechselt wird , die keinen vollständig qualifizierten Namen mit XML-Namespace haben.)

Wenn Sie denselben Stil auf andere Schaltflächen anwenden möchten, können Sie einfach mit der rechten Maustaste darauf klicken und "Vorlage bearbeiten / Ressource anwenden" auswählen und den Stil auswählen, den Sie gerade für die erste Schaltfläche hinzugefügt haben. Sie können diesen Stil sogar zum Standardstil für alle Schaltflächen machen, indem Sie die normalen Techniken zum Anwenden eines Standardstils auf Elemente in XAML verwenden.


5
Vielen Dank. Dies ist die einzige erträgliche Antwort hier
Jared Beach

13

Das hat bei mir gut funktioniert.

Tastenstil

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

Taste

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

Anmerkungen

  • Die Schaltfläche zeigt ein kleines blaues Kreuz an, ähnlich dem zum Schließen eines Fensters.
  • Wenn Sie den Hintergrund des Rasters auf "Transparent" setzen, wird ein Hittest hinzugefügt. Wenn sich die Maus also irgendwo über der Schaltfläche befindet, funktioniert dies. Wenn Sie dieses Tag weglassen, leuchtet die Schaltfläche nur auf, wenn sich die Maus über einer der Vektorlinien im Symbol befindet (dies ist nicht sehr nützlich).

1
Dies ist eine großartige Antwort, aber wie wäre es, wenn Sie die StrokeFarbe auch beim Schweben ändern Border, ohne dass sie nur über dem schwebt Path?
Nateous

1
Dieser x:Key="TransparentStyle"Teil und die Verwendung waren wichtig für mich, um dorthin zu gelangen ... Danke!
9.

6

Ich möchte nur meinen Schaltflächenstil aus meinem von mir verwendeten ResourceDictionary freigeben. Sie können den onHover-Hintergrund an den Stilauslösern frei ändern. " ColorAnimation To = * Ihr gewünschter Hintergrund (dh # FFCEF7A0)". Die Schaltfläche Hintergrund wird auch nach dem Status mouseOver automatisch auf den ursprünglichen Hintergrund zurückgesetzt. Sie können sogar festlegen, wie schnell der Übergang erfolgen soll.

Ressourcenwörterbuch

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

Alles was Sie tun müssen, ist den Stil zu nennen.

Beispielimplementierung

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

2

Eine etwas schwierigere Antwort, die ControlTemplate verwendet und einen Animationseffekt hat (angepasst von https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/customizing-the-appearance-of-an-existing- Kontrolle )

Definieren Sie in Ihrem Ressourcenwörterbuch eine Steuerungsvorlage für Ihre Schaltfläche wie die folgende:

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

In Ihrer XAML können Sie die Vorlage oben für Ihre Schaltfläche wie folgt verwenden:

Definieren Sie Ihre Schaltfläche

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

Ich hoffe es hilft


0

Zum Ändern des Schaltflächenstils

1. Ressourcenstile definieren

<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. Tastencode definieren

                           <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. Code dahinter

    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;

        }
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.