Laden...

WPF Elemente Laden

Erstellt von Turtle vor 15 Jahren Letzter Beitrag vor 15 Jahren 6.075 Views
Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren
WPF Elemente Laden

Hallo,
ich hab wiedermal eine Frage 😁
und zwar ich hab ein window mit menü und content bereich (siehe bild)
wenn ich jetzt auf einen punkt im menü klicke will ich im content bereich zum menüpunkt passende controls einblenden (checkbox, textbox, etc..)

wie geh ich das am besten an? muss ich für jeden menüpunkt einen eigenen contentbereich erstellen und den dann über das jeweilige clickevent sichtbar machen? wenn ja ist das ja beim erstellen des designs total unübersichtlich.

wie löst ihr solch eine aufgabenstellung?

Danke
mfg
Turtle

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

V
327 Beiträge seit 2005
vor 15 Jahren

Hallo,

ich würde in den Contentbereich ein LayoutControl setzen und dann für jeden Menüpunkt ein eigenes Control bauen. Wenn du auf den Menüpunkt klickt, Instanz vom Control erstellen und ContentLayoutRoot.Children.Add(Control).

dann habe ich noch enteprechende Animationen+Storyboards erstellt, damit die neuen Controls ein- und die alten ausgeblendet werden.

MFG Veasel

L
862 Beiträge seit 2006
vor 15 Jahren

Das ist die gleiche Vorgehensweise wie ein TabControl. Ich würde mir an deiner Stelle ein TabControl basteln und diesen per Template das Layout aus dem oberen Bild geben.

Ein TabControl besteht auch nur aus einem ContentBereich und einem Menü.
Und als Menü kannst du wiederum alles mögliche nehmen. Sei es ein Standard TabPanel, eine ListBox oder eine TreeView (wie ich in deinem Beispiel vermute).

P
67 Beiträge seit 2008
vor 15 Jahren

Hallo,
Erstell dir pro MenuItem ein neues Panel (oder UserControl) mit den entsprechenden Controls. Beim Instanzieren eines neuen MenuItem's übergibst du dann das Panel an die Tag-Property (des MenuItem's).
Nun sollte es eigentlich reichten, wenn du beim SelectedIndexChanged (oder wie auch immer das Event bei deinem Control heisst, wenn man ein anderes MenuItem auswählt)
den Tag ausliest und im Content-Bereich einfügst.

Religionskriege sind Konflikte zwischen erwachsenen Menschen, bei denen es darum geht, wer den cooleren, imaginaeren Freund hat

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Hallo,
Danke für die schnellen Antworten 👍

@veasel:
du meinst ein contentcontrol oder ?

@lector:
das tabcontrol wird wohl das leichteste sein.
hast du hirzu vieleicht ein tutorial oder einen bespielcode?

@pholmann
danke für den tipp wer aber wahrscheinlich lectors vorschlag annehmen da das tabcontrol diesbezüglich ja schon fix und fertig ist und "nur" das layout angepasst werden muss

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

P
67 Beiträge seit 2008
vor 15 Jahren

Da sowiso alle drei Vorschläge mit dem gleichen Prinzip funktionieren, passt es schon 😉

Religionskriege sind Konflikte zwischen erwachsenen Menschen, bei denen es darum geht, wer den cooleren, imaginaeren Freund hat

L
862 Beiträge seit 2006
vor 15 Jahren

Hier ein offizielles Beispiel:

http://msdn.microsoft.com/en-us/library/ms754137.aspx

In deinen Beispiel einfach das TabPanel durch etwas passendes ersetzen.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

gut danke für den link ich probier das mal aus

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

😄so ich spiel mich jetzt schon ein zeiterl mit dem tabcontrol und einem style dafür nur irgendwie komm ich einfach ned weiter 🙄

also ich hab ein tab control mit tab items nur wie bring ichs im style bzw template zam das ich den tab header verschieben kann bzw das es eben so aussieht wie oben am bild.

der link von lector hilft zwar weiter aber ... wtf 😁 irgendwie bin ich heute zu blöd dafür 🤔

hat das schon mal jemand gemacht und kann eventuell das ganze in xaml posten

danke
mfg
Turtle

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Du schreibst das ControlTemplate des TabControl so wie du dein Window im Bild oben geschrieben hast.
Mit den Unterschied dass du gewisse TabControl-spezifische Propertys setzt wie z.B.

<ContentPresenter 
              Margin="4"
              ContentSource="SelectedContent" />

Das stellt jetzt z.B. das Fenster rechts dar.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

also ich hab das mal versucht und bei mir sieht das aktuell folgendermassen aus (siehe code und bild):


    <Window.Resources>
        <Style TargetType="{x:Type TabControl}">
            <Setter Property="TabStripPlacement" Value="Left"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="Black"/>

        </Style>
        <Style TargetType="{x:Type TabItem}">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="Black"/>
        </Style>
    </Window.Resources>
    
    <Grid Width="Auto" Height="Auto" >
        <TabControl Margin="13,13,13,52" Name="tc_settings">
            <TabItem Header="Haupteinstellungen">TEST</TabItem>
            <TabItem Header="Aussehen">TEST2</TabItem>
        </TabControl>
    </Grid>

wenn ich jetzt ein control template hinzufüge mit dem content presenter den du gepostet hast bekomme ich die fehlermeldung: Die Eigenschaften von "ContentPresenter" können nicht gebunden werden, da für den Typ "System.Windows.Controls.Control" keine Eigenschaft mit dem Namen "Content" vorhanden ist.

weiters habe ich ja, wie im code zu erkennen, auch einen style für die tabitems erstellt und dort versucht den borderbrush und die borderthickness zu ändern ... leider wird dies nicht übernommen muss ich das auch in einem template machen?

so jetzt noch ein paar fragen die nicht unbedingt mit dem thema was zu tun hat: gibts irgendwo eine auflistung welche events es bei den einzelnen triggern gibt?

wenn ich einen targettype definiere z.b: TargetType="{x:Type TabControl}"
was sagt hier das x:Type aus bzw das x: generell?

sry für meine fragen aber ich versuch mich seit letzter woche in wpf einzuarbeiten und tu mir noch recht schwer. ich hab da zwar ein wpf buch liegen aber da finde ich auch nicht die antworten die ich suche.

ich hoffe ihr könnt mir da weiterhelfen

danke
mfg
Turtle

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Also erst einmal würde ich dir empfehlen wie im Beispiel nicht die Eigenschaften des TabControls zu setzen (vielleicht geht das aber auch) sondern ein komplett neues Template zu machen.

Dein Fehler hört sich so an als ob die angabe TargetType fehlt. Poste mal dein ControlTemplate.

Und x: ist ein Namespace. Der wird normal in jeder neuen XAML-Datei oben generiert

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Ich denke man könnte sagen x: stellt allgemeine Funktionen zur verfügung die nicht zwangsläufig was mit den Element zu tun haben in dem du x:... schreibst.

x:Name z.B. bewirkt eine Referenz auf die man im CodeBehind zugreifen kann.
x:Static sagt dass es sich nicht um eine Instanz sondern eine Klasse handelt.
x:Key ist eine Referenz für XAML (oder CodeBehind).

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

so ich hab jetzt versucht das ganze mittels templates zu lösen nur komme ich da einfach nicht weiter

ich hab 2 styles definiert, einen für das tabcontrol und einen für das tabitem mit jeweilse einem template:

style für tabcontrol:


<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
            <Setter Property="TabStripPlacement" Value="Left"/>
            <Setter Property="Foreground" Value="white"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="gray"/>
            <Setter Property="BorderThickness" Value="2"/>
            <Setter Property="Margin" Value="0"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="MinWidth" Value="10"/>
            <Setter Property="MinHeight" Value="10"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
                            <GroupBox Width="450" Height="250" ></GroupBox>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

style für das tabitem:


        <Style x:Key="TabItemStyle" TargetType="{x:Type TabItem}">
            <Setter Property="Padding" Value="12,2,12,2"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Grid>
                            
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>            
        </Style>

Im tab control hab ich eine Groupbox in welcher dann alle entsprechenden controls dargestellt werden sollen.
Was sollte ich für die tabitems verwenden, um diese darzustellen?

Mein TabControl selber sieht momentan so aus:


    <Grid >
        <TabControl  Name="tc_settings" Style="{DynamicResource TabControlStyle}">
            <TabItem Header="Haupteinstellungen" Style="{DynamicResource TabItemStyle}"></TabItem>
            <TabItem Header="Aussehen" Style="{DynamicResource TabItemStyle}"></TabItem>
        </TabControl>
    </Grid>

Ja jetzt weis ich irgendwie nicht weiter. Wie bringe ich den Header des TabItems in das Grid des Templates und wie bekomme ich den Content (soll sich aus buttons usw zuammensetzen) in die Groupbox?

Ich hoffe ich hab mich verständlich ausgedrückt wenn nicht bitte fragen.

Danke
mfg
Turtle

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Also erst einmal muss ich dir sagen wenn du ein Template schreibst werden sämtliche anderen Eigenschaften wie z.B. TabStripPlacement unwirksam ausser du beachtest diese per TemplateBinding in deinem Template.

ControlTemplate hat eine Eigenschaft TargetType (wo wie Style). Die solltest du setzen wenn du Fehler vermeiden willst.

Und zu allgemeinen Vorgehensweise schlage ich vor du kopierst dir einfach den Code aus dem Beispiel und änderst ihn so um wie es dir gefällt. Somit merkst du sofort wenn du eine Änderung machst die Fehler hervorruft.

Wichtig ist natürlich dass du den Beispielcode auch verstehst. Auch hier bietet es sich an einfach mit dem Beispielcode zumzuspielen und anhand der Ergebnisse zu lernen was die ganzen sachen im Template eigendlich machen.

5.742 Beiträge seit 2007
vor 15 Jahren

Hallo Turtle,

wie löst ihr solch eine aufgabenstellung?

entweder mit einem Frame und mehreren _Page_s. Wenn ich mich richtig erinnere, existiert bereits ein fertiges Navigate Command, das man dem entsprechendem Button zuweisen kann. Als CommandParameter verwendet man die Page, zu der man navigieren will.

Ich persönlich löse Probleme dieser Art, da ich MVVM verwende, mit einem ContentControl, das per Reflection (und einem Attribut "View") automatisch ein DataTemplate mit einem UserControl passend zum angezeigten ViewModel generiert.

Natürlich braucht man dazu nicht unbedingt Reflection und kann auch etwas schreiben wie:


<ListView Name="listView">
<!-- Enthält Items z.B. vom Typ NavigationTarget -->
</ListView>

<ContentPresenter DataTemplateSelector="[Ein DataTemplateSelector, der das entsprechende Template liefert.]">
   <ContentPresenter.Resources>
   <!-- Für jedes NavigationTarget ein eigenes Template -->
   </ContentPresenter.Resources>
</ContentPresenter>

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Hallo Lector,
d.h. wenn ich einen Style erstelle und in diesem Style ein Template erstelle überschreibt mir das Template automatisch den kompletten Style oder nur bestimmte Propertys ?

Wie kann ich in einem Template die im Style definierten Propertys binden? Das ist nämlich auch in dem von dir geposteten Link nicht ersichtlich (oder ich habs überlesen 🤔 )

Hallo winSharp93,
wo finde ich das fertige Navigate Command?
Könntest du mir vieleicht einer deiner Lösungen zukommen lassen damit ich mir diese einmal ansehen kann?

Danke euch beiden für die Hilfe.
mfg
Turtle

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Das Template überschreibt eigendlich nichts vom Style.

Das Template weist einem Control nur ein komplett neues aussehen zu.

Wenn ich z.B. einem Button per Template sage dass es wie ein Rectangle aussieht dann wird es auch als Rectangle angezeigt. Der Background des Buttons steht zwar noch im Button drin hat allerdings keine Auswirkungen da ich den Rectangle nicht gesagt habe was es denn damit zu machen hat.
Jetzt kann ich über TemplateBinding sagen
<Rectangle Fill={TemplateBinding Background}...>
Somit wird der Hintergrund des Buttons auf die Fill-Eigenschaft des Rectangles im Template übertragen. Wenn du jetzt für den TabControl ein richtiges Über-Template schreiben würdest müsstest du natürlich sämtliche Eigenschaften des TabControls aufs Template mappen. Ich würde dir allerdings davon abraten da ich denke dass du dieses Template nur 1 Mal verwenden wirst.

Ich an deiner Stelle würde den TabControl im Template sagen:

Du bist ein Grid mit 2 Spalten.
Links ist eine TreeView(ListView) drin.
Dieses Element bestimmt den TabHeader.
Rechts ist ein ContentPresenter drin.
Dieses Element zeigt den Innhalt an.

Kleine XAML-Skizze würde so aussehen (ungetestet und nur als Ansatz):


<TabControl>
<TabControl.Template>
<ControlTemplate TargetType=TabControl>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition ...>
<ColumnDefinition ...>
</Grid.ColumDefinitions>
<StackPanel Style={...} IsItemsHost="True"<-Wichtig />
<ContentPresenter ContentSource="SelectedContent" <-Auch Wichtig Grid.Column=2 />
</Grid>
</ControlTemplate>
</TabControl.Template>
</TabControl>

Allgemeines noch zu Styles. Ein Style macht nichts anderes als einem Control verschiedene Werte zuzuweisen (Setter, EventSetter). Man kann damit auch kleinere Abfragen machen (Trigger).

Ich hoffe es hilft dir weiter.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Hallo Lector,
ja du hilfst mir sehr weiter. Danke an dieser Stelle nochmals.

Ich hab mir das komplette Beispiel über den von dir geposteten Link heruntergeladen. In diesem Wird ein Template für den Tab Control und ein Template für die TabItems erstellt. Das müsste ich doch jetzt auch so machen (wenn ich es so mache wie du es vorschlägst)?

Würde in dem von dir geposteten xaml code in das stack panel der Tree view hineingehören und in diesem dann ein treeview item? Wie weise ich dann eigentlich dem Treeviewitem den Text zu?

mfg
Turtle

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Wichtig an dieser Stelle:

Sämtliche TabItems werden in dem Element dargestellt welches IsItemsHost=true definiert hat.

Dies ist jedoch eine Panel-Eigenschaft. Und TreeView ist meines Wissens kein Panel.

Wenn mein Beispiel funktioniert wird es links statt einer TreeView untereinander gestapelte Standard-TabHeaders anzeigen.

Du kannst jetzt dem StackPanel sagen:

Zeige alle TabItems (das sind die lustigen Controls die die Header darstellen) als TreeViewItems an. Dies machst du mit einem Style der ein Template beinhaltet. Genaueres zu TreeViewItems findest du bestimmt auf der gleichen MSDN-Seite wie bereits oben gepostet.

Vorher würde ich dir allerdings raten das TabControl soweit laufffähig zu machen dass es links StandardTabs und rechts den richtigen Innhalt anzeigt. Sonst kommt irgenwann ein Fehler und du weist nicht mehr was jetzt eigendlich schon funktioniert und wo du etwas falsch gemacht hast.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Du kannst jetzt dem StackPanel sagen:

Zeige alle TabItems (das sind die lustigen Controls die die Header darstellen) als TreeViewItems an. Dies machst du mit einem Style der ein Template beinhaltet. Genaueres zu TreeViewItems findest du bestimmt auf der gleichen MSDN-Seite wie bereits oben gepostet.

Dieses Style hat dann aber als TargetType das TabItem. Versteh ich das richtig?

wie kann ich eigentlich im Template den style für den contentpresenter definieren denn wenn ich einen style dort einbniden möchte kann ich ja nur die attribute des contentpresenter verwenden und der hat zum beispiel keinen foreground property.

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

582 Beiträge seit 2008
vor 15 Jahren

Hallo,
wie löst ihr solch eine aufgabenstellung?

Hallo Turtle,

die Möglichkeiten die die Kameraden hier schreiben sind bestimmt geeignet. Meiner Meinung nach, rennt man damit aber häufig mit der Kirche ums Dorf.

Simpel und einfach kannst du es jedoch am bestem mit einen Frame und Pages lösen. Ab auf die Pages mit deinen Controls und diese dann in den Frame geladen. Ein navigator-control ist nicht von nöten. Deine Menu-Buttons sorgen dann nur noch für die übergabe einer neuen URI an den Frame.

Einzige kleine Hürde ist die übergabe von Daten von einer Page an die nächste.

Um Resourcen zu schonen, kannst du z.B. dein Menu in ein Stackpanel mit Buttons verwandeln (oder ggf sogar Labels). Es muß ja lediglich abgefragt werden, ob geklickt wurde.

Ein TabControl macht gerade bei größeren Projekten den Quellcode unübersichtlich (für den Menschen). Ich nutze in mehereren meiner Programme nur noch eine Kombination aus beiden Technologien. Da ich mehrere "offene" Dokumente brauch.

Gruß dat Tala

L
862 Beiträge seit 2006
vor 15 Jahren

@Turtle:

Du brauchst dich im Template nicht um das Aussehen des ContentPresenters zu kümmern. Dieser zeigt einfach nur den Innhalt des TabItems an.

Und ja du solltest einen Style für die TabItems machen in denen du sagst dass sie wie ein TreeViewItem aussehen.

@Taladan

Von Unübersichtlichkeit kann nicht die Rede sein da ich die TabPages ebenfalls in eigende Dateien auslagern kann.
Vorteil des TabControl ist und bleibt wohl die Tatsache dass ich mich nicht um die Funktionalität kümmern brauche. Alles was zu machen ist kann ich in XAML schreiben. Und auch diesen Code kann ich wiederum auslagern um für Übersichtlichkeit zu sorgen.

Was allerdings nicht erspart bleibt ist der Aufwand sich einmal mit XAML-Styles/Template zu beschäftigen um zu verstehen wie man so etwas überhaupt macht.

582 Beiträge seit 2008
vor 15 Jahren

@ Lector.

Was genau meinst du mit funktionalität? Alles was ein TabPage kann, kann eine normale Page ebenso.

Gruß dat Tala

L
862 Beiträge seit 2006
vor 15 Jahren

Mit Funktionalität meine ich dass wenn man auf einen TabHeader klickt die Page geladen wird.
Und dass ich die Unterelemente auch per Binding ranhängen kann, da ein TabControl von ItemsControl erbt.
Ich meine nicht die funktionalität der Page da als Page ja alles mögliche drin stehen kann.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

So ich hab mir jetzt den Aufbau von Templates angesehen und bin auch ein Stück weiter gekommen, danke lector.

Ich habe aber noch ein Problem beim Aufbau des Tempaltes für die TabItems.

Mein Template für das TabControl sieht so aus:


        <Style TargetType="{x:Type TabControl}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabControl}">
                        <Grid >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <Border BorderBrush="Black" BorderThickness="2" Margin="-200,-20,0,0" Width="150" Height="380">
                                <StackPanel IsItemsHost="True" Grid.Column="0"/>
                            </Border>
                            <Border BorderBrush="Black" BorderThickness="2" Margin="200,-20,-350,0" Height="380">
                                <ContentPresenter ContentSource="SelectedContent" Grid.Column="1"/>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

mein Template für das TabItem sieht zur Zeit so aus (is natürlich ned fertig bzw passt es nicht):


        <Style TargetType="TabItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <TreeView>
                            <TreeViewItem/>
                        </TreeView>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Das ganze Gui sieht momentan so aus (siehe Bild).
Wie muss ich den TreeView oder die TreeViewItems jetzt "formatieren" dass das gewünschte Ergebnis herauskommt? Diesbezüglich steh ich irgendwie an.

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren
  
        <Style TargetType="TabItem">  
            <Setter Property="Template">  
                <Setter.Value>  
                    <ControlTemplate TargetType="{x:Type TabItem}">  
                        <TreeView>  
                            <TreeViewItem/>  
                        </TreeView>  
                    </ControlTemplate>  
                </Setter.Value>  
            </Setter>  
        </Style>  
  

Ein TabItem stellt genau ein Element in dem TabControl da.
Wenn du es so macht wird für jede TabPage eine TreeView erzeugt.
Versuche doch mal jedes Element nur als TreeViewItem darzustellen indem du die TreeView-Tags wegmachst.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Wenn du es so macht wird für jede TabPage eine TreeView erzeugt.

Hallo Lector,
ja das ist eben das Problem () 😃

Ich hab deinen Vorschlag auch schon probiert nur funktioniert das Umschalten zwischen den einzelnen Tabs nichtmehr?!

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Ich fasse noch mal zusammen.

Wenn du für jedes Element eine TreeView+TreeViewItem erzeugst funktioniert das Umschalten der Tabs.

Wenn du für jedes Element nur ein TreeViewItem erzeugst funktioniert das Umschalten der Tabs nicht mehr.

Habe ich das richtig verstanden?

Versuch doch trotzdem die Variante mit den TreeViewItems und sag dem StackPanel per Template dass dieses doch als TreeView fungieren soll.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

ja das hast du richtig verstanden.

d.h. ich soll jetzt für das stackpanel ein extra template erstellen?

zur zeit schaut das ganze so aus:


<Style TargetType="{x:Type TabItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <StackPanel>
                            <TreeViewItem  Height="Auto" Header="{TemplateBinding Property=TreeViewItem.Header}" Margin="0,5,0,0"/>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren
  
<Style TargetType="{x:Type TabItem}">  
            <Setter Property="Template">  
                <Setter.Value>  
                    <ControlTemplate TargetType="{x:Type TabItem}">  
                        <StackPanel>  
                            <TreeViewItem  Height="Auto" Header="{TemplateBinding Property=TreeViewItem.Header}" Margin="0,5,0,0"/>  
                        </StackPanel>  
                    </ControlTemplate>  
                </Setter.Value>  
            </Setter>  
        </Style>  
  

Wenn du es so machst ist mir klar dass du keinen Tab auswählen kannst. Du steckst nämlich jedes TabItem in ein einzelnes StackPanel. Das übergeordnete Haupt-StackPanel mit IsItemsHost=true bekommt so nicht mehr mit welchers Element ausgewählt ist.

Versuchs mal so:


<Style TargetType="{x:Type TabItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                            <TreeViewItem  Height="Auto" Header="{TemplateBinding Property=TreeViewItem.Header}" Margin="0,5,0,0"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Hallo Lector,
ich hatte das ganze auch schon ohne Stack Panel probiert aber es funktioniert dennoch nicht. Wenn ich jedoch ein TreeView drumherum gebe (es wird zwar für jedes TabItem ein TreeView erzeugt) und auf den Weissen bereich klicke funktioniert das umschalten sobald auf den Text selber geklickt wird funktioniert es nicht ... scheinbar wird hier das event nicht ausgelöst und das wird auch das Problem sein wenn man nur ein TreeViewItem verwendet.

Ich hab jetzt einmal einen TextBlock genommen und werde mir den entsprechend stylen.

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Est ist klar dass das Umschalten nur auf die TreeView selbst angetriggert wird. Ein TabItem löst den Event aus sobald auf ihn geklickt wird (in deinem Fall die TreeView), und nicht auf eines seiner Unterelemente (also das eigendliche TreeViewItem).

Wenn du dem jetzt einen TextBlock nimmst und ihn wieder ein Template zuweist wäre dass das selbe wie wenn du gleich das passende Template nimmst.

Du kannst auch versuchen um das TreeViewItem einen anderen (unauffälligen) Container zu wählen. Wie wäre es mit Label oder ContentControl?

Ich habe in meinen TabItemTemplate einen Border verwendet und das funktioniert wunderbar. Du kannst ihn natürlich auch unsichtbar machen.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Hallo Lector,
ich hab jetzt um den TextBlock ein Grid gelegt und 2 Spalten erstellt.
In der ersten soll ein Bild (Icon) dargestellt werden und in der 2 eben der TextBlock.
Das hat auch gut geklappt und hat eigentlich das gleiche Ergebnis erziehlt wie der TreeView (siehe Bild).

Was mir jedoch nicht so ganz klar ist, ist wie ich für jeden Menüpunkt ein anderes Bild zuweisen soll.
Das Template sieht zur Zeit so aus:
(ich hab die source nur mal zu testzwecken fix festgelegt)


<Style TargetType="{x:Type TabItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition Width="35"/>
                            </Grid.ColumnDefinitions>
                            <Image Grid.Column="0" Source="icons\CarOS_main_menu.jpg" Width="25" Height="30" HorizontalAlignment="Left" Margin="5,5,0,5"/>
                            <TextBlock Grid.Column="1"  Height="Auto" Text="{TemplateBinding Property=TabItem.Header}" Margin="-85,15,0,5" FontSize="12"/>
                        </Grid> 
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

ich hab schon probiert im tab item ein image zu erstellen und dann via templatebinding darauf zuzugreifen jedoch wird mir das bild, da es ja im tabitem erstellt wurde, im content bereich angezeigt.
kannst du mir da vieleicht weiterhelfen?

Danke
mfg
Turtle

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Du könntest ein einem ResourceDictionary auf Bilder verweisen und diesen Bildern den gleichen Key wie den TabHeadern geben und per TemplateBinding im Image darauf verweisen.
z.B. HaupteinstellungenIcon, AussehenIcon, MediaPlayerIcon...

<Image Grid.Column="0" Source="{TemplateBinding Property=TabItem.Header,Converter={StaticResource StringToImageConverter}}" Width="25" Height="30" HorizontalAlignment="Left" Margin="5,5,0,5"/>

In einem speziellen Converter (siehe IValueConverter) machst du aus dem String "MediaPlayer" das entsprechende Icon.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Also ich muss jetzt im resource Dictionary die Images definieren ? Muss ich dass dann im Tab Item irgendwie einbinden oder reicht es wenn ich dem image als key den namen es tabitems angebe?

EDIT: Bezüglich des Konverters:
Den kann man aber nicht direkt in xaml als resource definieren oder ?

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Du gibst dem Image den Namen des TabHeaders als Key.
Ich tendiere immer dazu noch ein Suffix wie 'Icon' ranzuhängen dass musst du allerdings wieder extra beachten.

Du musst aber nicht zwangsläufig ein ResourceDict nehmen. Kannst auch aufs lokale Filesystem zugreifen im Converter kannst du ja an hand des Headerstring das Bild von irgendwo herladen.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Du musst aber nicht zwangsläufig ein ResourceDict nehmen. Kannst auch aufs lokale Filesystem zugreifen im Converter kannst du ja an hand des Headerstring das Bild von irgendwo herladen.

Also das hab ich nicht zusammengebracht hast du da vieleicht ein fertiges Beispiel?

Ich hab das jetzt einmal über eine StringCollection probiert weis jetzt aber nicht wie ich der Image Source das ganze zuweisen kann.

Das ganze schaut zur Zeit so aus:


 <Window.Resources>   
        
        <local:IconStringCollection x:Key="Icons"/>
        
        <Style TargetType="{x:Type TabControl}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabControl}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <Border BorderBrush="Black" BorderThickness="2" Margin="-200,-20,0,0" Width="160" Height="380" Background="White">
                                <StackPanel IsItemsHost="True" Grid.Column="0"/>
                            </Border>
                            <Border BorderBrush="Black" BorderThickness="2" Margin="200,-20,-350,0" Height="380">
                                <ContentPresenter ContentSource="SelectedContent" Grid.Column="1"/>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="{x:Type TabItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition Width="35"/>
                            </Grid.ColumnDefinitions>
                            <Image Grid.Column="0" Source="{????}" Width="25" Height="30" HorizontalAlignment="Left" Margin="5,5,0,5"/>
                            <TextBlock Grid.Column="1"  Height="Auto" Text="{TemplateBinding Property=Header}" Margin="-85,15,0,5" FontSize="12"/>
                        </Grid> 
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

Wie muss ich der Source die StringCollection in welcher die Pfade zu den Icons (in der richtigen Reihenfolge) stehen zuweisen?

<Image Grid.Column="0" Source="{????}" Width="25" Height="30" HorizontalAlignment="Left" Margin="5,5,0,5"/>

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Source ist vom Typ ImageSource.
Davon abgeleitet ist BitmapImage.
Du bindest jetzt genau wie beim Text an den Header und benutzt einen Converter um den Text (oder w/e) in ein BitmapImage zu konvertieren bzw. anhand des Strings ein BitmapImage zu laden.
Ein Beispiel zu den Converter habe ich schon gepostet

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Hallo,
d.h. wenn ich das ganze doch über den von dir vorgeschlagenen Weg machen würde

{TemplateBinding Property=TabItem.Header,Converter={StaticResource StringToImageConverter}}

bekomme ich in der Convert Funktion über die Variable Value den Header und müsste diesen halt entsprechend konvertiert zurückliefern um das Image anzuzeigen. Hab ich das so richtig Verstanden?

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.

L
862 Beiträge seit 2006
vor 15 Jahren

Genau.

Probiers doch einfach mal aus.

Turtle Themenstarter:in
129 Beiträge seit 2007
vor 15 Jahren

Passt, danke für deine Hilfe das Menü ist fertig 😃 hat bestens funktioniert.

mfg
Turtle

Wer fragt, ist ein Narr für fünf Minuten. Wer nicht fragt, bleibt ein Narr für immer.