[WPF] Trigger IsMouseOver ContentControl Child verändern


  • Administrator

    Ich komme irgendwie gerade nicht weiter. Ich habe ein ContentControl , welches ein ControlTemplate bekommt. Im Template sind verschiedene Children definiert unteranderem ein <ContentPresenter Content="{TemplateBinding ContentControl.Content}" /> . Dies ist dann wiederrum eine einfache Linie ( <Line> ). Jetzt möchte ich gerne, dass wenn die Maus über dem ContentControl ist, die Linie in einer anderen Farbe erscheint. Wie krieg ich das sinnvoll gedreht?

    Grüssli



  • Zeig mal bitte dein XAML. Die ÜBerlegung das mit einem Trigger zu machen ist gut.
    Aber so ohne XAML is schwer zu sagen 😃



  • Also die Farbe der Linie beeinflusst du direkt im Template durch n Trigger

    z.B.:

    <ControlTemplate ...>
        <Grid>
            <Line x:Name="PART_Line" Brush="Red" ... />
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="PART_Line" Property="Brush" Value="Pink" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    

    Wenn die Linie aber nicht im ControlTemplate deines Controls liegt, benötigt diese einen eigenen Style

    z.B.:

    <Style>
        <Setter Property="Brush" Value="Red" />
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Brush" Value="Pink" />
            </Trigger>
        </Style.Triggers>
    </Style>
    

  • Administrator

    @CSL,
    Danke, ist aber leider nicht ganz, was ich möchte. Also, hier etwas XAML Code:

    <Windows.Resources>
      <Style x:Key="ContentControlStyle" TargetType="ContentControl">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate>
              <Grid>
                <!-- bla bla bla -->
                <ContentPresenter Content="{TemplateBinding ContentControl.Content}">
              </Grid>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </Windows.Resources>
    
    <DockPanel LastChildFill="False">
      <ContentControl DockPanel.Dock="Top" Height="3" UseLayoutRounding="True"
                      Style="{StaticResource ContentControlStyle}">
        <Line X1="0" Y1="1" X2="1" Y2="1" Stretch="Fill" Stroke="White" StrokeThickness="1" />
      </ContentControl>
    </DockPanel>
    

    Ich möchte hier nun einen IsMouseOver Trigger einbauen, damit wenn IsMouseOver vom ContentControl true ist, das DependencyProperty Stroke von Line im ContentControl auf Yellow wechselt.

    Grüssli



  • Hmm - komisches Konstrukt ^^

    Idee:
    Im ControlTemplate im Trigger das Foreground des ContentControl auf Yellow stellen, und in der Line dann Stroke gegen des Foreground Binden.


  • Administrator

    CSL schrieb:

    Hmm - komisches Konstrukt ^^

    Tz, du unterschätzt meine künstlerische Ader! :p

    Ich habe es nun gelöst. Allerdings unteranderem dadurch, weil mir aufgefallen ist, dass man das Konstrukt vereinfachen kann 😃

    Schlussendlich ist es nun darauf rausgelaufen, dass Line Teil eines ControlTemplate von einem Custom Control ist. Daher kann ich Stroke an Foreground binden, was auch Sinn macht. Einziges Problem war noch, dass IsMouseOver nur dann ausgelöst wurde, wenn die Maus über der Linie war, obwohl das Custom Control grösser war. Allerdings konnte ich das mit einem Rectangle mit Fill auf Transparent lösen. Und über diese Rectangle wird dann die Linie gezeichnet.

    Oder wollt ihr wieder etwas XAML? *seufz*

    <Canvas>
      <Canvas.Resources>
        <Style x:Key="LineThumbStyle" TargetType="{x:Type test:MoveThumb}">
          <Setter Property="Cursor" Value="SizeAll" />
          <Setter Property="Foreground" Value="White" />
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate>
                <Grid>
                  <Rectangle Fill="Transparent" />
                  <Line X1="0" Y1="1" X2="1" Y2="1" Stretch="Fill"
                        Stroke="{TemplateBinding Thumb.Foreground}" StrokeThickness="1" />
                </Grid>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
          <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
              <Setter Property="Foreground" Value="Yellow" />
            </Trigger>
          </Style.Triggers>
        </Style>
      <Canvas.Resources>
    
      <test:MoveThumb Canvas.Top="50" Canvas.Left="300" Width="100" Height="3"
                      UseLayoutRounding="True"
                      Style="{StaticResource LineThumbStyle}"
                      DataContext="{Binding RelativeSource={RelativeSource Self}}"/>
    
    </Canvas>
    

    Dann kann ich nun endlich diese kleine Fallstudie abschliessen und die gewonnen Erkenntnisse ins Hauptprojekt übertragen 🙂

    Danke für eure Hilfe.

    Grüssli



  • Das Rectangle brauchst du nicht, du hast das mit dem Transparent richtig erkannt, so macht man das, aber du hast da schon ein Grid, setz doch einfach den Background des Grids auf Transparent, dann kannst du das Rectangle weg schmeißen.

    Aber so richtig gefällt mir es nicht, wenn du die Linie im Template hast, dann Sprich "Im Control Template"! Trigger direkt die Linie an und setz die Farbe.
    TextBlocks usw erben gerne mal die Foreground.

    <Style x:Key="LineThumbStyle" TargetType="{x:Type test:MoveThumb}">
        <Setter Property="Cursor" Value="SizeAll" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type test:MoveThumb}">
                    <Grid Background="Transparent">
                        <Line x:Name="PART_Line" X1="0" Y1="1" X2="1" Y2="1" Stretch="Fill" Stroke="White" StrokeThickness="1" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="PART_Line" Property="Stroke" Value="Yellow" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    So lässt du dein Foreground unangetastet und hast keine bösen Side-effects, kürzer ist es zudem.


  • Administrator

    Finde ich aber nicht wirklich gut. So kann ich nicht die Farbe der Linie ändern. Mit meiner Lösung kann ich einfach Foreground eine andere Farbe zuweisen. Zusätzlich werde ich dann in MoveThumb ein HighlightColor DependencyProperty einführen. Ich wüsste nicht, wie Foreground irgendetwas anderes beeinflussen sollte in diesem ControlTemplate . Das ControlTemplate bestimmt schliesslich das Aussehen und wie man sieht, hat es keinen TextBlock . Da kann kein TextBlock vorkommen. Und wenn auch ein TextBlock vorkommen würde, dann wäre es nicht verkehrt, wenn die Schrift darin die gleiche Farbe hat wie die Linie.

    Grüssli



  • Oka, im diesem Fall hast du recht.
    Ich nahm an das Beispiel war nur gekürzt und da ist noch mehr in dem Control außer eine Linie.


Anmelden zum Antworten