Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

1

17.03.2016, 00:01

[C#] [MVVM] ItemsControl soll für jedes Model ein ViewModel erstellen

Hallo Leute!

Letztens habe ich schon was zu MVVM gefragt - das funktioniert nun - besonders die Commands sind genial. ;)

Nun eine weitere Frage zu MVVM: Ich habe eine Collection von Models. Jedes Model benötigt C#-Code für die korrekte Anzeige - reine DataTemplates + ItemsControl funktionieren da nicht. Nun meine Frage, wie ich in einem ItemsControl sage, dass es mir für jedes Model (Item) ein ViewModel erzeugen soll.

Ich hatte bis jetzt folgende Idee:

Quellcode

1
2
3
4
5
6
7
<ItemsControl ItemsSource="{Binding FaderList}">
    <ItemsControl.ItemTemplate>
         <DataTemplate>
               <l:FaderView DataContext="{Binding}"/>
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public partial class FaderView : UserControl
{
    // Eigenschaften
    public new object DataContext
    {
        get
        {
            return base.DataContext;
        }
        set
        {
            base.DataContext = new FaderViewModel()
            {
                Model = value as Fader
            };
        }
    }
    // Konstruktor
    public FaderView()
    {
        InitializeComponent();
    }
}
Kurze Erklärung: Ich weise meiner View als DataContextdas Model zu und die View erzeugt sich dann dafür ein ViewModel und speichert das Model in dessen Model Eigenschaft.
Problem: Die "überschriebene" Eigenschaft DataContext wird nicht aufgerufen bzw. verwendet - hab ich mit nem Haltepunkt herausgefunden, der nicht angesprungen wird. Warum kann ich mir auch denken, aber mir viel nix anderes ein... :D

Und so nebenbei denke ich, dass das auch nicht der richtige Weg ist sowas zu veranstalten... :D Das ist nicht MVVM like, wenn ich das Pattern in dieser Hinsicht richtig verstehe!

Ich hoffe man kann mir helfen - Google konnte es nicht. :(
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

2

17.03.2016, 00:11

Dann nimm doch einfach eine Collection der entsprechenden ViewModels, und weiße diesen das
jeweilige Model zu. Das DataTemplate kann bleiben wie es ist, das ist gut so.

Btw. geht das auch wenn verschiedene Models in der Collection sind bzw. dann wie oben beschrieben verschiedene ViewModels:

Quellcode

1
2
3
4
5
6
7
        <DataTemplate DataType="{x:Type ViewModels:FooVM}">
            <Views:FooView DataContext="{Binding}" />
        </DataTemplate>
        
        <DataTemplate DataType="{x:Type ViewModels:BarVM}">
            <Views:BarView DataContext="{Binding}" />
        </DataTemplate>

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

3

17.03.2016, 00:19

Und wie bzw. wann wird aus meiner ModelCollection eine ViewModelCollection erzeugt? Muss das ViewModel der View, die das ItemsControl enthält diese ViewModelCollection erstellen? Was passiert, wenn sich die ModelCollection ändert?
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

4

17.03.2016, 00:23

Und wie bzw. wann wird aus meiner ModelCollection eine ViewModelCollection erzeugt?


Direkt beim Laden/Instanzieren der Models.

Was passiert, wenn sich die ModelCollection ändert?


Solange die eine ObservableCollection nutzt, wird die Collection das merken und auch der Rest der GUI wird informiert.

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

5

17.03.2016, 00:26

Meine Models müssen also in einer ObservableCollection gespeichert werden und das (übergeordnete) ViewModel bindet an das Changed-Ereignis. Wenn das Aufgerufen wird, dann wird die ObservableCollection mit den ViewModels aktualisiert. So korrekt?
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

6

17.03.2016, 07:42

Deine ViewModels, welche die Models enthalten, sind in einer ObservableCollection des übergeordneten ViewModel.
Du musst da gar nix binden, sobald du eine einem Control ne ObservableCollection zuweist, abboniert das Control
das changed Event automatisch. Genauso wie im Falle von INotifyPropertyChanged bei ViewModel und View.

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

7

17.03.2016, 09:09

Quick and Dirty hat recht. ObserableCollection mit ViewModels an das Itenscontrol über das DependencyProperty ItemsSource binden, und für jeden ViewModeltypen ein DataTemplate anlegen. Total super, straight forward und Sinn der Technik :)

EDIT: Hier nochmal kurz ein paar Schnipsel, wie man es gut machen kann:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class ViewModelBase {}

class SpecificViewModel1 : ViewModelBase {}

class SpecificViewModel2 : ViewModelBase {}

class SuperSpecificViewModel : SpecificViewModel {}

class Container
{
    public readonly ObservableCollection<ViewModelBase> Children { get; private set; }
    
    Container()
    {
        Children = new ObservableCollection<ViewModelBase>();
    }
}

<DataTemplate DataType="{x:Type SpecificViewModel1}">
</--  -->
</DataTemplate>

<DataTemplate DataType="{x:Type SpecificViewModel2}">
</DataTemplate>

<DataTemplate DataType="{x:Type SuperSpecificViewModel}">
</DataTemplate>

<Grid>
    <ItemsControl ItemsSource="{Binding Children}" />
</Grid>

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »TrommlBomml« (17.03.2016, 10:17)


CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

8

17.03.2016, 14:54

Ja, euer Prinzip hab ich schon verstanden, so schwer ists nicht. ;)

Nur brauche ich die Models auch nochmal ohne ein ViewModel in einer Liste. Diese Liste kann sich während der Laufzeit verändern. Wenn also ein Model in dieser Liste hinzugefügt wird, dann wird auch in der ViewModelListe ein ViewModel + das neue Model angelegt. Das mache ich mit Code Behind in dem übergeordneten ViewModel, mit der in meinem letzten Post beschriebenen Vorgehensweise. Stimmt das so?
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

9

17.03.2016, 18:54

Ja stimmt alles so, bzw. nichts von dem was du anmerkst, wäre so wie
wir es dir vorgeschlagen haben nicht machbar.
Die ObservableCollection ist eine List und somit beliebig erweiterbar.
Hast du eine Liste der ViewModels hast du indirekt auch eine Liste der Models.

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

10

17.03.2016, 20:59

Ja, euer Prinzip hab ich schon verstanden, so schwer ists nicht. ;)

Nur brauche ich die Models auch nochmal ohne ein ViewModel in einer Liste. Diese Liste kann sich während der Laufzeit verändern. Wenn also ein Model in dieser Liste hinzugefügt wird, dann wird auch in der ViewModelListe ein ViewModel + das neue Model angelegt. Das mache ich mit Code Behind in dem übergeordneten ViewModel, mit der in meinem letzten Post beschriebenen Vorgehensweise. Stimmt das so?


Geht schon, finde ich aber nicht so doll. Wenn der View etwas tut, was die ViewModels verändert, sollte es das idealerweise mit einem Binding tun, oder ein Command im ViewModel auslösen. Ich habe schon manchmal View mit Code Behind auf ein ViewModel zugreifen lassen, das macht aber Wiederverwendung eklig.

Model sehe ich in deinem Code ehrlich gesagt keins, nur View und ViewModel. Kannst du dein Problem vielleicht mal konkretisieren?

Werbeanzeige