Laden...

DataTemplate in einem ContentControl

Erstellt von CoderboyPB vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.153 Views
C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren
DataTemplate in einem ContentControl

Hallo

Aus einem YT Tutorial habe ich folgendes Konstrukt, um die Views zu switchen:


<Window
:
xmlns:viewmodels="clr-namespace:ViewChanger.ViewModels"
xmlns:views="clr-namespace:ViewChanger.Views"
/>

<Window.Resources>
        <DataTemplate DataType="{x:Type viewmodels:RedViewModel}">
            <views:RedView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewmodels:BlueViewModel}">
            <views:BlueView/>
        </DataTemplate>
</Window.Resources>

<Button Content="Red View" Click="RedView_clicked"/>
<Button Content="Blue View" Click="BlueView_clicked"/>

<ContentControl Content="{Binding}" Grid.Column="1"/>
</Window>

Die beiden Button Funktionen setzen leere ViewModels als DataContext:


private void RedView_clicked(object sender, RoutedEventArgs e)
        {
            DataContext = new RedViewModel();
        }

        private void BlueView_clicked(object sender, RoutedEventArgs e)
        {
            DataContext = new BlueViewModel();
        }

Die Views sind einfach nur leere UserControls mit einem farbigen Hintergrund.

Ich verstehe das jetzt so: Das ContentControl kann mit dem DatenTyp (Beispiel) RedViewModel nichts anfangen, und sucht dann in den Resources die mit dem zugehörigen Typ raus, was hier ein DataTemplate ist, und dieses enthält die View (UserControl) mit dem roten Hintergrund, so dass das ContentControl in rot erscheint.
Die Zwischenstufe mit dem DataTemplate wird verwendet, weil dieses eine DataType Eigenschaft hat.

Habe ich das soweit richtig verstanden?

Falls ja, warum, funktioniert folgendes nicht:


<ContentControl>
            <DataTemplate>
                <views:RedView/>
            </DataTemplate>
        </ContentControl>

Hier erhalte ich einfach nur 'System.Windows.DataTemplate' als Ausgabe, aber im Grunde genommen ist das doch auch nichts anderes, als die Variante oben, nur, dass ich die Werte direkt setze?

PS: Das die Überschrift Mist ist, weiß ich, aber wer ne bessere Idee hat, kann sie gerne editieren, mir ist nichts sinnvolleres eingefallen. Sorry.

4.931 Beiträge seit 2008
vor 4 Jahren

Ein DataTemplate macht nur dort Sinn, wo auch ein Template erwartet wird, z.B. bei den <Window.Resources> oder auch bei <ListBox.ItemTemplate>, s.a. Übersicht über Datenvorlagen (wobei ich den englischen Artikel "Data Templating Overview" empfehlen würde - wegen der mangelhaften maschinellen Übersetzung ins Deutsche; kann man oben rechts mit "Auf Englisch lesen" einstellen).
Und ein ContentControl stellt die Daten ansonsten direkt dar (wenn es kein ContentElement ist), daher erhältst du eben "System.Windows.DataTemplate" (der interne Typname, der mittels ToString() zurückgegeben wird).

Und auch deine Sätze hinter

Ich verstehe das jetzt so: ...

sind nicht ganz korrekt.
Durch das Content="{Binding}" wird der aktuelle DataContext, der mittels der beiden Buttons jeweils gesetzt wird, dargestellt.
Durch die Angabe von DataType beim <DataTemplate>wird ein sog. "implizites Template" (s.a. MVVM – WPF Data Templates) erstellt, welche jeweils die beiden Klassen RedViewModel und BlueViewModel direkt mit der View verknüpft, so daß diese dann angezeigt wird.

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

Gerade von der Dialyse nach Hause gekommen.
Ich sag jetzt erst mal Danke, und werde mir die Links mal zu Gemüte führen 😃

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

So, habe mir die Links jetzt mal durchgelesen:
Das deckt sich eigentlich 1:1 mit dem, was ich bisher auch über DataTemplates wusste.
So weit so gut, aber was ich immer noch nicht verstehe:

Warum funktioniert:


<Window.Resources>
        <DataTemplate DataType="{x:Type viewmodels:RedViewModel}">
            <views:RedView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewmodels:BlueViewModel}">
            <views:BlueView/>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        
        <ContentControl Content="{Binding}" Grid.Column="1"/>
        
    </Grid>
</Window>

aber:



        <ContentControl Grid.Column="1">
            <DataTemplate>
                <views:BlueView/>
            </DataTemplate>
        </ContentControl>

nicht?

Das ist doch im Grunde genommen beides das Gleiche, nur dass das die View manuell zugewiesen wird, aber die Struktur ist doch dieselbe, warum wird die View also oben angezeigt, und im manuellen Beispiel nur die toString() Methode ausgegeben?

4.931 Beiträge seit 2008
vor 4 Jahren

Was soll denn das DataTemplate deiner Meinung nach beim ContentControl bewirken?
Ein Template ist eine Vorlage, welche anderswo eingesetzt werden kann.

Möchtest du einfach nur


<ContentControl Grid.Column="1">
    <views:BlueView/>
</ContentControl>

?

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

Das DataTEmplate hat ja ne DataType Eigenschaft, diese wird durch Binding gesetzt, und darauf hin dann entweder das DataTemplate mit der roten oder blauen View geladen.

Das DT ist also quasi die Verbindung vom ViewModel zur verwendeten View.

Aber wieso funktioniert das nicht im zweiten Beispiel mit der 'Fußgängermethode'

WO liegt der UNTERSCHIED???

Ah, ich hab's glaub ich:
Das Template wird gar nicht eingefügt, sondern nur der INHALT, ist es das?