Laden...

MVVM - Frame Navigation (Alternativen)

Erstellt von resper vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.271 Views
R
resper Themenstarter:in
33 Beiträge seit 2017
vor 6 Jahren
MVVM - Frame Navigation (Alternativen)

Hallo,

wenn ich ein Programm ähnlich wie auf dem Bild, was ich am Ende des Posts angefügt habe umsetzen möchte, wie gehe ich am besten vor?

Ich habe das MainWindow, welches mein MainViewModel nutzt. In der XAML Datei habe ich jetzt Buttons, die den Inhalt des Hauptbereiches verändern sollen.
Um beim Beispiel der Auftrags und Lagerverwaltung zu bleiben: z.B. eine Liste der Bestellungen, eine Liste der Kunden, eine Liste der Lieferanten.

In meinem ersten Versuch ohne MVVM habe ich das ganze über einen Frame gelöst, was sich aber bei Nutzung des MVVM Prinzips als nicht mehr ganz so einfach heraus stellt.

Der Contentbereich soll mit dem MainViewModel kommunizieren können, weil dort auch Login und Logout verwaltet wird und jeder Nutzer hat eigene Daten.

Hatte schon überlegt ob ich alles Inhalte in das Main Windows packe und dann durch die Buttons die Visibility ändere, was aber ein sich nicht sehr Elegant sein dürfte. Welchen Weg würdet ihr gehen?

Meine Inhalte in etwas gekürzter Version:

MainWindow.xaml


    <DockPanel>
        <StackPanel DockPanel.Dock="Left">
            <Label Content="[res][per]" />
            <Button>
                Bestellung
            </Button>
            <Button>
                Lieferanten
            </Button>
        </StackPanel>
        <DockPanel DockPanel.Dock="Top">
            <Label Content="Programm Titel" DockPanel.Dock="Left"/>
            <StackPanel Orientation="Horizontal" DockPanel.Dock="Right" HorizontalAlignment="Right">
                <Label Content="Eingeloggt als:" />
                <Label Content="{Binding LoginName}" />
                <Button Content="Logout" Command="{Binding CommandLogout}" />
            </StackPanel>
        </DockPanel>
        <!-- HIER SOLL DER CONTENT HIN -->
    </DockPanel>
</Window>

MainWindow.xaml.cs


    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }
    }

MainWindowViewModel.cs


using resperLaMa.Commands;
using resperLaMa.Connections;
using resperLaMa.Helper;
using resperLaMa.Models;
using resperLaMa.Pages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace resperLaMa.ViewModels
{
    class MainWindowViewModel : BaseViewModel
    {

        private string loginName;
        private int loginId;

        public string LoginName
        {
            get { return loginName; }
            set
            {
                loginName = value;
                OnPropertyChanged("LoginName");
            }
        }

        public int LoginId
        {
            get { return loginId; }
            set
            {
                loginId = value;
                OnPropertyChanged("LoginId");
            }
        }

        public ICommand CommandLogout { get; set; }

        public MainWindowViewModel()
        {
           CommandLogout = new RelayCommand(parameter => SendLogOut());
        }


        public void SendLogOut()
        {
            LoginId = -1;
        }
    }
}
P
441 Beiträge seit 2014
vor 6 Jahren

Meine erste Idee wäre den Contentbereich durch ein <ContentControl /> zu realisieren, wobei sich die Content Property an eine Property aus dem MainViewModel binden ließe.
Dann könntest du im MainViewModel z.B. UserControls bereitstellen die den Inhalt darstellen.

Da du diese im MainVM initialisierst könntest du auch direkt Events binden für alles, was du mit dem Inhalt ausserhalb des MainVM machen möchtest.

R
resper Themenstarter:in
33 Beiträge seit 2017
vor 6 Jahren

Danke für den Tipp. Ich suche mal nach Beispielen im Netz.

R
resper Themenstarter:in
33 Beiträge seit 2017
vor 6 Jahren

Also ich habe jetzt das ganze mit UserControls umgesetzt.

In meiner MainWindow.xaml für jede Unterseite:

        <DataTemplate DataType="{x:Type local2:StartPageViewModel}">
            <local1:StartPage/>
        </DataTemplate>

der Bereich ContentControl:

<ContentControl x:Name="Pages" DockPanel.Dock="Right" Content="{Binding SelectedViewModel}"/>

MainWindowsViewModel.cs hinzugefügt:


private object selectedViewModel;

public object SelectedViewModel
{
    get { return selectedViewModel; }
    set { selectedViewModel = value; OnPropertyChanged("SelectedViewModel"); }
}

mit

SelectedViewModel = new StartPageViewModel();

kann ich jetzt den Contentbereich steuern.

Für den ContentBereich habe ich jetzt für jede Unterseite eine xaml und cs Datei und ein ViewModel.

z.B.:

  • StartPage.xaml
  • StartPage.xaml.cs
  • StartPageViewModel.cs

StartPage.xaml


<StackPanel>
    <Label Content="Test Seite" />
    <Button Content="Andere Seite" Command="{Binding CommandAnotherPage}"/>
</StackPanel>

StartPage.xaml.cs

public partial class StartPage : UserControl
{
    public StartPage()
    {
        InitializeComponent();
    }
}

StartPageViewModel.cs


public ICommand CommandSaveAdminPw { get; set; }
public StartPageViewModel()
{
    CommandAnotherPage= new RelayCommand(parameter => anotherPage());
}

private void anotherPage()
{
    
}

Wie bekomme ich es jetzt hin, den Contentbereich aus dem StartPageViewModel heraus zu wechseln?

Wie bekomme ich von meinem StartPageViewModel heraus Zugriff auf zum Beispiel auf die LoginId (siehe Code Startbeitrag) in dem MainWindowsViewModel?

EDIT

Ok, das mit den Daten übergeben kann ich ja einfach mit

SelectedViewModel = new StartPageViewModel(LoginId);

machen oder?

Den Content durch einen Button im Content ändern, habe ich jetzt mit folgendem Bindig gelöst:


<Button Content="Home" Command="{Binding Path=DataContext.CommandStartView, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>

Jetzt versuche ich es noch hinzubekommen, dieses aus dem Programmcode herraus hin zu bekommen.

4.939 Beiträge seit 2008
vor 6 Jahren

Hallo,

die Login-Daten solltest du besser in einer eigenen Model-Klasse halten und diese dann z.B. über eine Service-Klasse von den ViewModels aus ansprechen (anstatt die ViewModels sich gegenseitig zu referenzieren).