Entwickler-Ecke

WPF / Silverlight - MVVM Menü Binding mit verschiedenen ViewModels


m.keller - Fr 02.09.16 12:11
Titel: MVVM Menü Binding mit verschiedenen ViewModels
Hallo Entwicklergemeinde,

Ich habe eine Problem.
Entweder macht gerade mein Gehirn schlapp oder ich habe das noch nicht richtig verstanden.

Ich habe vor eine WPF Anwendung zu erstellen die auf der Linken Seite ein Menü zum Bedienen der Hauptanzeige, diese soll sich rechts daneben befinden.
Das Problem ist, ich habe verschieden Views und die Verschiedenen ViewModels, wie bekomme ich die nun Gebunden an die Einzelnen Menüpunkte und wie erreiche ich, dass die Anzeig dann auch nur den angeklickten Punkt bzw. das Passende Usercontroll anzeigt?

Ich habe leider nichts passendes gefunden.
Vielleicht kennt jemand ein Tutorial.

Danke schon mal für die Hilfe.


Th69 - Fr 02.09.16 12:30

Hallo,

such mal mit dem Begriff "Navigation" danach.

Falls du schon mal mit Prism gearbeitet hast: Navigation Using the Prism Library for WPF [https://github.com/PrismLibrary/Prism/blob/master/Documentation/WPF/60-Navigation.md#prism-region-overview].


m.keller - Mo 05.09.16 10:06

Nein noch nicht.
Ich will das auch erst ein mal nicht anfassen, weil ich das ganze Prinzip erst ein mal verstehen möchte.
Zum vereinfachen später von anderen Projekten greife ich dann vielleicht darauf zurück.

Danke aber schon mal.
Ich habe das jetzt Zwar so weit aufgebaut wie in

https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
Allerdings komme ich nicht dazu, dass er die Seite Wechselt.


Palladin007 - Mo 05.09.16 11:11

Du musst noch SelectedItem an CurrentPageViewModel binden

XML-Daten
1:
SelectedItem="{Binding Path=CurrentPageViewModel, Mode=TwoWay}"                    

Das fehlt in dem Beispiel

Moderiert von user profile iconTh69: XML-Tags hinzugefügt


m.keller - Mo 05.09.16 11:22

user profile iconPalladin007 hat folgendes geschrieben Zum zitierten Posting springen:
Du musst noch SelectedItem an CurrentPageViewModel binden

SelectedItem="{Binding Path=CurrentPageViewModel, Mode=TwoWay}">

Das fehlt in dem Beispiel


Ok Danke, gibt es den überhaut eine Möglichkeit bei ItemsControl diese Option zu nutzen?


Palladin007 - Mo 05.09.16 11:26

Klar, warum sollte das nicht gehen?


m.keller - Mo 05.09.16 11:32


XML-Daten
1:
2:
3:
4:
5:
6:
7:
<ItemsControl ItemsSource="{Binding Views}" DockPanel.Dock="Bottom">
    <ItemsControl.ItemTemplate>
        <DataTemplate >
            <Button Content="{Binding DisplayName}" Command="{Binding  DataContext.ChangeViewCommand , RelativeSource={RelativeSource AncestorType={x:Type Window}}}"  />
        </DataTemplate>                             
    </ItemsControl.ItemTemplate>                          
</ItemsControl>


In welchem Bereich ist das möglich?

Moderiert von user profile iconTh69: C#- durch XML-Tags ersetzt


Palladin007 - Mo 05.09.16 11:34

Ist eine Property vom ItemsControl, also beim ItemsControl

Blödsinn, die Klasse Selector hat die SelectedItem-Property. Für Auflistungen, in denen ein Item ausgewählt werden kann, kann also ListView oder ListBox verwendet werden.


m.keller - Mo 05.09.16 11:39

Kann ich dort nicht finden.
Und wenn ich es hinzufüge kann er es nicht Kompilieren.


Th69 - Mo 05.09.16 11:43

Dann zeige uns deinen Code und die Fehlermeldung des Compilers.


Palladin007 - Mo 05.09.16 11:46

Stimmt, ich hab mich geirrt :D

SelectedItem gehört zu der Klasse Selector und die erbt von ItemsControl.

Probier mal ListView oder ListBox. ListView erbt von ListBox und die erbt von Selector, hat also auch die SelectedItem-Property
Aus dem Kopf weiß ich den Unterschied nicht mehr, aber es kann sein, dass Du explizit den Border abstellen musst.


PS:
Es gibt die Properties SelectedItem, SelectedValuePath und SelectedValue, den Unterschied kannst Du hier [http://stackoverflow.com/questions/4902039/difference-between-selecteditem-selectedvalue-and-selectedvaluepath] nachlesen.


m.keller - Mo 05.09.16 12:19

Danke da habe ich die Property.


Ich habe den Fehler gefunden.

Weiß aber nicht woran es genau liegt.

In dem Beispielt ist der Command so angegeben

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
public ICommand ChangePageCommand
    {
        get
        {
            if (_changePageCommand == null)
            {
                _changePageCommand = new RelayCommand(
                    p => ChangeViewModel((IPageViewModel)p),
                    p => p is IPageViewModel);
            }
 
            return _changePageCommand;
        }
    }


Ich habe mir eine Class erstellt die das ICommand erbt.
Und diese als Commandtyp verwendet.
Im Konstruktor habe ich dann diesen mit der Methode zugewiesen.

Konstruktor

C#-Quelltext
1:
2:
3:
4:
5:
 
            
            ChangeViewRelay = new RelayCommand(p => ChangeViewModel((ViewModelBase)p), true);

       }


Der Command


C#-Quelltext
1:
2:
3:
4:
5:
 public RelayCommand ChangeView
        {
            get;
            set;
        }


Die Methode

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
 private void ChangeViewModel(ViewModelBase viewModel)
        {
            if (!Views.Contains(viewModel))
            {
                Views.Add(viewModel);
            }
            CurrentPageView = Views.FirstOrDefault(vm => vm == viewModel);
        }


Palladin007 - Mo 05.09.16 12:30

Wenn ich mich nicht irre, brauchst Du die Property garnicht selber setzen, das macht der Selector von sich aus.
Wenn der Benutzer in der UI auf eines der Items klickt und das dadurch ausgewäjlt wird, dann landet es in der SelectedItem-Property und (wenn das Binding TwoWay ist) auch in deiner Property im ViewModel.


m.keller - Mo 05.09.16 12:53

es geht scheibar beides.

vielen Dank