Background-Color eines Buttons bei MouseOver overriden

  • WPF

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    Background-Color eines Buttons bei MouseOver overriden

    Guten Tag zusammen,

    ich möchte die Hintergrundfarbe eines Buttons ändern, wenn man die Maus drüberbewegt. Hier mein Code:

    XML-Quellcode

    1. <Button Grid.Row="1" Style="{StaticResource Navigationsbuttons}">
    2. <Grid>
    3. <Grid.ColumnDefinitions>
    4. <ColumnDefinition Width="5*"/>
    5. <ColumnDefinition Width="95*"/>
    6. </Grid.ColumnDefinitions>
    7. [...]
    8. </Grid>
    9. </Button>


    Und in der Application.xaml:

    XML-Quellcode

    1. <Style x:Key="Navigationsbuttons" TargetType="{x:Type Button}">
    2. <Setter Property="Background" Value="Transparent"/>
    3. <Setter Property="BorderThickness" Value="0"/>
    4. <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    5. <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    6. <Style.Triggers>
    7. <Trigger Property="IsMouseOver" Value="True">
    8. <Setter Property="Background" Value="Yellow"/>
    9. </Trigger>
    10. </Style.Triggers>
    11. </Style>


    Leider funktioniert das nicht und die Hintergrundfarbe des Button wird bei einem MouseOver nicht geoverridet... Spinn ich? ich finde den Fehler nicht... Habs auch schon mit DynamicResource in Zeile 1 des ersten Codes versucht...

    Hat jemand eine Idee?
    Hallo kafffee

    Du bist in letzter Zeit ja ganz schön aktiv ;)
    Freut mich das wieder jemand zur WPF gefunden hat.

    Bei einem Button ist das so eine Sache da dieser mehr oder weniger Nativ gerendert wird und Theme-Abhängig ist. Hier musst du das Template überschreiben.

    XML-Quellcode

    1. <Window.Resources>
    2. <SolidColorBrush x:Key="MyYellowBackground" Color="Yellow"></SolidColorBrush>
    3. <Style x:Key="Navigationsbuttons" TargetType="{x:Type Button}">
    4. <Setter Property="OverridesDefaultStyle" Value="True"/>
    5. <Setter Property="Background" Value="Transparent"/>
    6. <Setter Property="BorderThickness" Value="0"/>
    7. <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    8. <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    9. <Style.Triggers>
    10. <Trigger Property="IsMouseOver" Value="True">
    11. <Setter Property="Background" Value="Yellow"/>
    12. </Trigger>
    13. </Style.Triggers>
    14. </Style>
    15. <Style x:Key="SimpleButtonStyle" TargetType="{x:Type Button}">
    16. <Setter Property="Template">
    17. <Setter.Value>
    18. <ControlTemplate TargetType="{x:Type Button}">
    19. <Grid>
    20. <Border Background="Transparent" VerticalAlignment="Stretch" CornerRadius="2" HorizontalAlignment="Stretch"/>
    21. <Border x:Name="BorderPressed" Opacity="0" Background="{StaticResource MyYellowBackground}" VerticalAlignment="Stretch" CornerRadius="2" HorizontalAlignment="Stretch"/>
    22. <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" x:Name="MainContent" />
    23. </Grid>
    24. <ControlTemplate.Triggers>
    25. <Trigger Property="IsMouseOver" Value="True">
    26. <Setter Property="Background" Value="Yellow"/>
    27. </Trigger>
    28. <Trigger Property="IsMouseOver" Value="True">
    29. <Trigger.EnterActions>
    30. <BeginStoryboard>
    31. <Storyboard>
    32. <DoubleAnimation Storyboard.TargetName="BorderPressed" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.2"/>
    33. </Storyboard>
    34. </BeginStoryboard>
    35. </Trigger.EnterActions>
    36. <Trigger.ExitActions>
    37. <BeginStoryboard>
    38. <Storyboard>
    39. <DoubleAnimation Storyboard.TargetName="BorderPressed" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.2"/>
    40. </Storyboard>
    41. </BeginStoryboard>
    42. </Trigger.ExitActions>
    43. </Trigger>
    44. </ControlTemplate.Triggers>
    45. </ControlTemplate>
    46. </Setter.Value>
    47. </Setter>
    48. </Style>
    49. </Window.Resources>
    50. <Grid>
    51. <Button Style="{StaticResource SimpleButtonStyle}" Content="Mein Testbutton">
    52. </Button>
    53. </Grid>


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Nofear23m

    Um Gottes Willen... Da wird der Code ja gleich richtig übersichtlich. :P Dann nehm ich einfach ein Border, das geht für meinen Zweck genauso...

    Edit: Jetzt fällt mir doch noch mal was zu dem Thema ein. Wenn ich eine Farbe gegeben hab, nehmen wir Yellow, wie kann ich den Alpha Wert (der ja glaube ich die Transparenz darstellt) oder aber auch die Sättigung ändern, mal abseits von der Eigenschaft Opacity eines Controls, die sich dann ja auch auf den gesamten Content des Controls auswirkt und nicht nur auf den Background...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    Hallo

    kafffee schrieb:

    Da wird der Code ja gleich richtig übersichtlich

    Naja, da man solche Styles und Templates ja ohnehin in Resource-files auslagert (ich mach da immer für jede controlart ein File), ist mir das eher schnuppe. ;)

    kafffee schrieb:

    wie kann ich den Alpha Wert (der ja glaube ich die Transparenz darstellt)

    Da gibt es viele Wege wie z.b. über Converter und der gleichen. Am einfachsten ist es aber die Opacity direkt auf dem Brush zu setzen.

    XML-Quellcode

    1. <SolidColorBrush Color="SkyBlue" Opacity=".9" />


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Nofear23m

    OK hab das jetzt so:

    XML-Quellcode

    1. <SolidColorBrush x:Key="ButtonHighlightFarbe" Color="Yellow" Opacity="0.5"/>
    2. <Style x:Key="Navigationsbuttons" TargetType="{x:Type Border}">
    3. <Setter Property="Background" Value="Transparent"/>
    4. <Setter Property="BorderThickness" Value="0"/>
    5. <Style.Triggers>
    6. <Trigger Property="IsMouseOver" Value="True">
    7. <Setter Property="Background" Value="{DynamicResource ButtonHighlightFarbe}"/>
    8. </Trigger>
    9. </Style.Triggers>
    10. </Style>


    Aber beim MouseOver wird weder nach Yellow noch nach Opacity="0.5" gewechselt... Wenn ich in Zeile 8 direkt Yellow reinschreib gehts komischerweise...
    Hallo

    Funzt bei mir tadellos.
    Ansonsten poste bitte auch den XAML in welchem du den Border definierst.

    XML-Quellcode

    1. ​<Window.Resources>
    2. <SolidColorBrush x:Key="ButtonHighlightFarbe" Color="Yellow" Opacity="0.5"/>
    3. <Style x:Key="Navigationsbuttons" TargetType="{x:Type Border}">
    4. <Setter Property="Background" Value="Transparent"/>
    5. <Setter Property="BorderThickness" Value="0"/>
    6. <Style.Triggers>
    7. <Trigger Property="IsMouseOver" Value="True">
    8. <Setter Property="Background" Value="{DynamicResource ButtonHighlightFarbe}"/>
    9. </Trigger>
    10. </Style.Triggers>
    11. </Style>
    12. </Window.Resources>
    13. <Grid>
    14. <Border Margin="10" Style="{StaticResource Navigationsbuttons}"/>
    15. </Grid>


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Nofear23m

    Das ging ja schnell mit dem Video über MVVM :thumbsup: Habs mir grad schon angeschaut...

    Voilà die Definition meines Border. Zeile 9 hab ich bisschen gekürzt (Data=[test]), aber das tut ja glaub ich nichts zur Sache...

    XML-Quellcode

    1. <Border Name="brdSuchen" Grid.Row="1" Style="{DynamicResource Navigationsbuttons}" MouseLeftButtonDown="BrdSuchen_MouseLeftButtonDown">
    2. <Grid>
    3. <Grid.ColumnDefinitions>
    4. <ColumnDefinition Width="5*"/>
    5. <ColumnDefinition Width="95*"/>
    6. </Grid.ColumnDefinitions>
    7. <Rectangle Name="icoSuchenHighlight" Grid.Column="0" Fill="{DynamicResource VordergrundfarbeBrush}" Width="3"/>
    8. <Canvas Grid.Row="1" Grid.Column="1" Name ="icoSuchen" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Width="32" Height="32">
    9. <Path Fill="{DynamicResource VordergrundfarbeBrush}" Data="[test]"/>
    10. </Canvas>
    11. </Grid>
    12. </Border>
    Hallo

    Funzt bei mir.

    Aber....

    Lass das mit den {DynamicResources} verwende wo möglich {StaticResources}. Warum erkläre ich in meiner Tutorialreihe.

    Weiters ist mir nur aufgefallen (hat jetzt nicht direkt mit dem zu tun das es bei dir nicht tut. Was das Betrifft würd ich es mal in einem TestWindow probieren, evtl. funkt dir was dazwischen was du gerade nicht am Schirm hast) das du für das Canvas eine Width angibst obwohl die Breite ja durch die Column des Grids vorgegeben ist, wenn dann gebe die Width für den Border an.
    Wenn du einen Border als Button "missbrauchst" musst du einige Events mehr abonnieren. Was ist mit der Tastatur? Tabstop? Nur so als Idee. Bleibt natürlich dir überlassen.

    Hat es einen Grund ein Canvas zu verwenden?

    Nur so am Rande. Sag mal was genau du hier Basteln willst. Screenshot? Evtl. gibts ja einen viel besseren Weg. Ich denke das ganze soll ja wiederverwendbar sein oder?

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Nofear23m

    Die DynamicResources verwende ich, weil ich quasi der ganzen Anwendung eine Hauptfarbe gebe (einen "Skin" wenn du so willst), die der User durch Auswahl in einer ComboBox zur Laufzeit wählen kann.

    Ohne die Größenangaben bei dem Canvas erscheint das Symbol nicht in der Mitte der Schaltfläche. Habs auch schon ohne bzw. auch mit Horizointal/VerticalAlignment Center und auch Stretch probiert, da erscheint das Symbol überall, nur nicht in der Mitte der Schaltfläche...

    An Events reicht mir erstmal das MouseDown für das Border.

    Das Canvas verwende ich anstatt eines Image, weil mir die Symbole als XAML-Code vorliegen und auch weil ich so einfach die Farbe des Symbols setzen kann ohne viel Aufwand...

    Im ersten Screenshot siehst du, wie es werden soll, sobald man mit der Maus drüberfährt. Nur anstatt das Rots (ich hab das zu Demozwecken direkt in die Backgroundeigenschaft geschrieben (in Zeile 8 Post#5) hätte ich gern das Türkis, in dem auch der Rest des Programms ist, nur halt mit weniger Opacity.
    Im zweiten Screenshot siehst du, wie es bei mir aussieht mit dem Code den ich gepostet habe.

    Edit: Habs jetzt mal extrahiert und in ein extra Programm gepackt, da funktionierts auch komischerweise mit der Opacity. Willst du mal den kompletten Code bzw. du hast gesagt das geht auch über Converter oder dergleichen...?
    Bilder
    • screenshot navigationsleiste.jpg

      64,33 kB, 978×598, 55 mal angesehen
    • screenshot navigationsleiste2.jpg

      65,39 kB, 975×600, 51 mal angesehen

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „kafffee“ ()

    Hallo

    Ich hab dir jetzt mal ein Beispiel erstellt. OK, in diesem Beispiel sind nun recht viele Resourcendateien aber das ist einfach weil ich das gerne so mach.
    Ich habe immer die Colors, Brushes, Margins usw. ausgelagert.

    Aber.... Du kannst den Button jetzt auch wirklich als Button mit all seinen Funktionalitäten nutzen wie ein Button so genutzt werden kann. Also auch mit Commands (du wirst ja sicher auch mal mit Binding arbeiten (hoffe ich)).
    So ist das denke ich eine runde Sache.

    Hier das ControlTemplate im eigentlichen:

    XML-Quellcode

    1. <Style x:Key="MyNonStyleButton" TargetType="{x:Type Button}" BasedOn="{StaticResource DefaultButton}">
    2. <Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisualStyle}" />
    3. <Setter Property="Padding" Value="0" />
    4. <Setter Property="Background" Value="Transparent"/>
    5. <Setter Property="Template">
    6. <Setter.Value>
    7. <ControlTemplate TargetType="{x:Type ButtonBase}">
    8. <Border x:Name="border" Style="{StaticResource MyIsMouseOverBorderStyle}"
    9. BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0" SnapsToDevicePixels="True">
    10. <Grid>
    11. <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}"
    12. Content="{TemplateBinding Content}"
    13. ContentStringFormat="{TemplateBinding ContentStringFormat}"
    14. HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    15. Margin="{TemplateBinding Padding}" RecognizesAccessKey="True"
    16. SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
    17. VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
    18. <Border HorizontalAlignment="Left" Margin="0" Height="{TemplateBinding Height}"
    19. Style="{StaticResource MyLeftButtonBorderStyle}">
    20. <Border Width="3" BorderThickness="0" SnapsToDevicePixels="True" Background="{StaticResource ButtonLeftLineBrush}"/>
    21. </Border>
    22. </Grid>
    23. </Border>
    24. </ControlTemplate>
    25. </Setter.Value>
    26. </Setter>
    27. </Style>


    Zu dem Button gehören nun ein paar Styles welche über {StaticResource} eingebunden sind:

    XML-Quellcode

    1. <Style x:Key="MyIsMouseOverBorderStyle" TargetType="{x:Type Border}">
    2. <Setter Property="Background" Value="Transparent" />
    3. <Style.Triggers>
    4. <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
    5. <Setter Property="Padding" Value="0" />
    6. <Setter Property="Background" Value="{StaticResource HoverIconBrush}"/>
    7. </DataTrigger>
    8. </Style.Triggers>
    9. </Style>
    10. <Style x:Key="MyLeftButtonBorderStyle" TargetType="{x:Type Border}">
    11. <Setter Property="Visibility" Value="Hidden" />
    12. <Setter Property="Background" Value="Blue"/>
    13. <Style.Triggers>
    14. <DataTrigger Binding="{Binding IsMouseOver,ElementName=border}" Value="True">
    15. <Setter Property="Visibility" Value="Visible" />
    16. </DataTrigger>
    17. </Style.Triggers>
    18. </Style>
    19. <Style x:Key="DefaultButton" TargetType="{x:Type Button}">
    20. <Setter Property="Margin" Value="{StaticResource DefaultMargin}" />
    21. <Setter Property="Padding" Value="0" />
    22. </Style>
    23. <Style x:Key="MyFocusVisualStyle">
    24. <Setter Property="Control.Template">
    25. <Setter.Value>
    26. <ControlTemplate>
    27. <Rectangle SnapsToDevicePixels="true" Fill="Transparent"
    28. Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
    29. StrokeThickness="1" StrokeDashArray="1 2" />
    30. </ControlTemplate>
    31. </Setter.Value>
    32. </Setter>
    33. </Style>


    Hier sind ein paar Brushes verknüpft:

    XML-Quellcode

    1. <SolidColorBrush x:Key="DefaultIconBrush" Color="{StaticResource DefaultIconColor}"></SolidColorBrush>
    2. <SolidColorBrush x:Key="HoverIconBrush" Color="{StaticResource HoverIconColor}" Opacity=".5"></SolidColorBrush>
    3. <SolidColorBrush x:Key="ButtonLeftLineBrush" Color="{StaticResource ButtonLeftLineColor}"></SolidColorBrush>


    usw... Ich denke du weist ja was ich meine.
    Schaut auf der ersten Blick wild aus, aber im Grunde gehts ja nur um das Template.

    Hier ein Screenshot mit MouseOver:




    Und das Projekt habe ich dir auch angehängt.

    Grüße
    Sascha
    Dateien
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Nofear23m

    Sei mir nicht böse aber das ist für mich zu viel Code auf einmal momentan.

    Da mein Problem offensichtlich ein Compilerfehler ist (imo) und ich da wirklich auf keinen grünen Zweig komme, hab ich mich entschlossen, einfach einen Border um das Border zu zeichnen bei MouseOver, anstatt den Hintergrund zu ändern. Sieht auch geil aus.

    Nur bleibt da zwischen dem Rahmen um das Border und meinem Rectangle eine feine Linie (und wenn es auch nur ein Pixel breit ist), als hätte das Rectangle einen Margin. Hab den Margin mal explizit auf 0 gesetzt, aber das bleibt so. Siehe Screenshot.

    Weisst du warum und wie man das ändern kann?

    PS (Off Topic): Du schreibst davon, Teile der Resourcen in andere Dateien auszulagern. Kann ich auch ein komplettes Grid auslagern in eine echte extra Datei, also nicht nur seine Resourcen (z.B. Style) sondern die Defintion und den Content?
    Bilder
    • screenshot navigationsleiste3.jpg

      15,52 kB, 222×278, 42 mal angesehen
    Hallo

    Bin dir nicht Böse, aber sei du mir nicht Böse wenn ich dir sage das du dir mit solchen Workarounds Probleme einhandelst, Binding auf ein Command bei einem Border kannst du vergessen. Also MVVM, Binding oder der gleichen hast du dir somit verspielt.

    kafffee schrieb:

    Da mein Problem offensichtlich ein Compilerfehler ist

    Ne =O

    kafffee schrieb:

    Hab den Margin mal explizit auf 0 gesetzt

    Setze mal das Padding (siehe meinen code)

    kafffee schrieb:

    Kann ich auch ein komplettes Grid auslagern in eine echte extra Datei, also nicht nur seine Resourcen

    Ja, ein UserControl oder ein CustomControl

    kafffee schrieb:

    das ist für mich zu viel Code auf einmal momentan

    Wenn das zu viel code ist wie machst du deine Anwendung dann Theme-fähig? Soll jetzt keinerlei Kritik sein, dachte nur das ich bei dir ruig etwas komplizierteres Posten könne wenn du Skins in deine Anwendung implementierst. ?(

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:

    Also MVVM, Binding oder der gleichen hast du dir somit verspielt.

    Ich sage ja nur für den Moment. Ich muss jetzt erstmal eine Weile mit dem schon Gelernten rumspielen dass sich das erstmal festigt...

    Nofear23m schrieb:

    Setze mal das Padding (siehe meinen code)

    Geht auch nicht... Naja nicht so schlimm das kann ich verkraften...

    Nofear23m schrieb:

    Ja, ein UserControl oder ein CustomControl

    Alles klar :)

    Nofear23m schrieb:

    Soll jetzt keinerlei Kritik sein, dachte nur das ich bei dir ruig etwas komplizierteres Posten könne wenn du Skins in deine Anwendung implementierst.

    Ja also ich bin ja wirklich kompletter XAML-Neuling. VB.Net darf ruhig etwas mehr sein, mein aktuelles Projekt ist jetzt glaub ich bei so 2000 Zeilen Code... Ich möchte das Projekt jetzt auf WPF umstellen... Erstmal nur die View designen.
    Hallo

    kafffee schrieb:

    Ja also ich bin ja wirklich kompletter XAML-Neuling.

    Achso, sorry. OK, habe ich falsch interpretiert. Spricht aber ja für dich, denn das bedeutet das deine Post das suggerieren. ;)

    Grüße

    PS: Wenn ein Thema erledigt denk bitte daran oben das rote Quadrat mit einem Doppelklick zu streicheln um damit das Thema als erledigt zu markieren.
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##