Laden...

TextBlock Visibility in Abhängigkeit von TabItem-Focus; welcher Trigger?

Erstellt von GeneVorph vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.350 Views
G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 4 Jahren
TextBlock Visibility in Abhängigkeit von TabItem-Focus; welcher Trigger?

Hallo,

Folgende Funktionalität möchte ich herstellen:

In einem TabControl habe ich im Header jedes TabItems zwei TextBlocks. Im ersten TextBlock befindet sich die Bezeichnung des TabItems, im zweiten TextBlock ein Symbol-Font.
Ich möchte, dass jeweils der Text im ersten TextBlock des ausgewählten TabItems lesbar ist, sobald das TabItem Focus besitzt, d.h. die Visibility des ersten TextBlocks von Collapsed auf Visible geändert wird.

In Code behind ist es zwar ganz einfach, ich möchte es aber - wenn möglich - im xaml-code lösen.

hier mein Code:

<TabItem x:Name="Item2" GotFocus="Item2_GotFocus" LostFocus="Item2_LostFocus">                    
                    <TabItem.Header>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock x:Name="Text2" FontSize="14" FontFamily="Quicksand" VerticalAlignment="Center">
                                <TextBlock.Style>
                                    <Style TargetType="TextBlock">
                                        <Setter Property="Visibility" Value="Collapsed"/>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding ElementName=Item2, Path=IsFocused}" Value="True">
                                                <Setter Property="Visibility" Value="Visible"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </TextBlock.Style>
                            Große<LineBreak/>Leistungsnachweise                                
                            </TextBlock>
                            <TextBlock Margin="20,0,0,0" FontSize="32" FontFamily="APPFONT" VerticalAlignment="Center">B</TextBlock>
                        </StackPanel>
                    </TabItem.Header>
                </TabItem>

Leider funktioniert obiger Code nur einmal - danach wird die Bezeichnung nicht mehr angezeigt, d.h. die Visibility des TextBlocks Text2 bleibt ständig auf "Collapsed".

Die Funktionalität sollte aber ständig gegeben sein: erhält das jeweilige TabItem Fokus, dann soll der jeweilige TextBloxk1 im Header sichtbar sein, verliert das TabItem den Fokus, soll der jewilige TextBlock collapsed sein.

Wahrscheinlich benutze ich gar nicht den richtigen Trigger? Brauche ich einen EventTrigger, der auf den Item2_GotFocus-Event reagiert? Leider scheinen EventTrigger nur mit StoryBoards zu funktionieren, aber ich will ja gar nichts animieren?

Zur Verdeutlichung ein Bild im Anhang (der von mir verwendete Font ist selbsterstellt, funktioniert also nicht bei jedem...).

Gruß Vorph

301 Beiträge seit 2009
vor 4 Jahren

Das Problem warum es nicht funktioniert:

Im Scope deines Styles gibt es kein Element Item2 auf das du zugreifen könntest. Aus deinem Style heraus auf Elemente zugreifen kannst du höchsten indem du den Visual Tree nach oben läufst. Das könntest du machen indem du mit FindAncestor nach dem erstmöglichen TabItem suchst und dich daran bindest.

https://stackoverflow.com/questions/18431043/wpf-relativesource-in-style

G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 4 Jahren

Hallo KroaX und vielen Dank für deine Antwort.

Leider ist der Link etwas "beyond my scope" 😉
Aber ich denke, ich weiß in etwa wie es gemeint ist. Daher drei zusätzliche Fragen:

  1. gerade weil

[...]Style heraus auf Elemente zugreifen kannst du höchsten indem du den Visual Tree nach oben läufst. verstehe ich jetzt immer noch nicht, warum es beim ersten mal klappt?

  1. So wie ich das verstehe, müsste ich z. B. in der Window-Resource ein Style-Template für den Typ TextBlock anlegen Ist das richtig?
    Im Beispiel kann man es nicht sehen, aber ich möchte ja nur bestimmte TextBlocks ansprechen - das heißt ich arbeite hier mit x:Key?

Das könntest du machen indem du mit FindAncestor nach dem erstmöglichen TabItem suchst und dich daran bindest.

Muss ich das dann auch im Template unterbringen? Die Frage ist dann wo? Und wie kann ich an FindAncestor binden, denn der würde dann ja erst gesucht.
Es gibt keine Möglichkeit hier mit den x:Name-Attributen zu arbeiten? Denn die sind ja für die Tabs bekannt...

Vielen Dank,
schöne Grüße
Vorph

5.657 Beiträge seit 2006
vor 4 Jahren

Wenn du es so machen willst, wie du gezeigt hast, dann solltest du, wie von KroaX vorgeschlagen, FindAncestor verwenden. Wenn du das nicht kennst, mußt du wenigstens mal in die Doku dazu schauen. Deine Fragen ergeben jedenfalls in dem Zusammenhang wenig Sinn.

Ansonsten kann man soetwas auch immer über eine entsprechende Eigenschaft im ViewModel lösen. Die Eigenschaft enthält das aktuell ausgewählte Tab, und sowohl das TabItem als auch die Visibility-Eigenschaften werden einfach daran gebunden.

Davon abgesehen heißt die Eigenschaft für das aktuell ausgewählte Tab IsSelected und nicht IsFocused.

Einen Trigger brauchst du dafür auch nicht unbedingt, du kannst einfach direkt binden und einen BooleanToVisibilityConverter verwenden.

Siehe dazu auch: [Artikel] MVVM und DataBinding

Weeks of programming can save you hours of planning

G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 4 Jahren

So, ich muss zwei Dinge kurz klarstellen:

  1. ich code rein hobbymäßig, wenn Beruf und Familie es gestatten (d.h. alle paar Wochen mal ein paar Stunden). Einiges habe ich schon verstanden, vieles noch nicht.

  2. Anfängerfehler passieren daher immer wieder. Und manche Fehler sind halt "dumm". So wie dieser.

Problem gelöst!

Mein xaml-code funktioniert - lediglich die Event Handler gaaanz obe im xaml-code blieben unbemerkt. GetFocus und LostFocus. Dort stand tatsächlich noch Code drin, der die Visibility der TextBlocks auf Collapsed setzt. Kein Wunder, dass es nicht funktioniert hat.

Es geht also einfach (ganz einfach sogar) mit den Triggern. Man bekommt meinen Code zum Laufen, wenn man die beiden Event Handler löscht. Ohne FindAncestor, ohne BooleanToVisibilityConverter. Das sind andere Wege, die mit Sicherheit zur selben Lösung führen.

Und nachdem ich mir nun Asche auf's Haupt gestreut habe: den xaml-Code mit den Triggern hatte ich in einer Kaffee-Pause auf ne Serviette gekritzelt - da bin ich doch ein bissl stolz, dass ich zumindest das scheinbar verstanden habe 😉

Trotzdem Danke für eure Hilfe - das Forum ist und bleibt Wissensfundus Nr. 1.
Gruß
Vorph