Hallo zusammen,
hab mich nebenbei wieder mal mit WPF & MVVM beschäftigt, nach einiger Abwesenheit
Hab mir also mein Grundlagen aufgebaut und als erstes Navigation eingebaut. Diese funktioniert auch sehr gut, allerdings habe ich ein Problem: meine ViewModels werden zweimal aufgerufen, sodass am Ende meine Bindings nicht funktionieren da die entsprechenden Eigenschaften nicht gesetzt sind.
Für die ViewModels habe ich meine Basisklasse:
Spoiler anzeigen
Mit der Methode
Zum Navigieren benutze ich folgende Methode:
Spoiler anzeigen
Und hier hole ich mir das richtige Viewmodel:
Spoiler anzeigen
Das funktioniert auch alles wundar, ich kann navigieren und die richtige View wird auch angezeigt, aber nicht die Daten, die ich in
Hier ein Beispiel wie das aktuell aussieht:
Spoiler anzeigen
Meine Hauptview ist folgende:
Spoiler anzeigen
Ich bin da aktuell ein wenig überfragt, warum genau meine Viewmodels zweimal erzeugt werden.
Über jeden Tipp bin ich dankbar!
hab mich nebenbei wieder mal mit WPF & MVVM beschäftigt, nach einiger Abwesenheit
Hab mir also mein Grundlagen aufgebaut und als erstes Navigation eingebaut. Diese funktioniert auch sehr gut, allerdings habe ich ein Problem: meine ViewModels werden zweimal aufgerufen, sodass am Ende meine Bindings nicht funktionieren da die entsprechenden Eigenschaften nicht gesetzt sind.
Für die ViewModels habe ich meine Basisklasse:
C#-Quellcode
- public abstract class ViewModelBase : ModelBase
- {
- private static readonly string[] HostProcesses = new string[] { "XDesProc", "devenv", "WDExpress", "WpfSurface" };
- public abstract string Name { get; }
- protected bool IsInDesignMode
- {
- get
- {
- return HostProcesses.Contains(Process.GetCurrentProcess().ProcessName);
- //return (bool)(DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue);
- }
- }
- public abstract void Initialize();
- }
Mit der Methode
Initialize()
rufe ich Viewmodelspezifische Methoden zu Initialisierung auf (zum Beispiel laden von Einstellungen).Zum Navigieren benutze ich folgende Methode:
C#-Quellcode
- void NavigateTo(Navigate obj)
- {
- switch (obj)
- {
- case Navigate.Sql:
- CurrentViewModel = ViewModelContainer.Instance.GetViewModel(typeof(SqlViewModel));
- break;
- case Navigate.Ftp:
- CurrentViewModel = ViewModelContainer.Instance.GetViewModel(typeof(FtpViewModel));
- break;
- case Navigate.Übersicht:
- break;
- }
- CurrentViewModel?.Initialize();
- RaisePropertyChanged(nameof(CurrentViewModel));
- }
Und hier hole ich mir das richtige Viewmodel:
C#-Quellcode
- public sealed class ViewModelContainer
- {
- private static readonly Lazy<ViewModelContainer> lazy = new Lazy<ViewModelContainer>(() => new ViewModelContainer());
- public static ViewModelContainer Instance { get { return lazy.Value; } }
- private List<ViewModelBase> viewModels = new List<ViewModelBase>();
- private ViewModelContainer()
- {
- }
- public ViewModelBase GetViewModel(Type type)
- {
- var vm = viewModels.SingleOrDefault(v => v.GetType() == type);
- if (vm == null)
- {
- var newVM = (ViewModelBase)Activator.CreateInstance(type);
- viewModels.Add(newVM);
- return newVM;
- }
- return vm;
- }
- }
Das funktioniert auch alles wundar, ich kann navigieren und die richtige View wird auch angezeigt, aber nicht die Daten, die ich in
Initialize()
lade.Hier ein Beispiel wie das aktuell aussieht:
C#-Quellcode
- public override void Initialize()
- {
- Databases = new ObservableCollection<string>();
- LoadSqlSettings();
- }
- private void LoadSqlSettings()
- {
- var fileContent = SaveAndLoad.ReadFile("SqlSettings");
- if (!string.IsNullOrWhiteSpace(fileContent))
- {
- SqlSettings = SaveAndLoad.Deserialize<SqlSettings>(fileContent);
- RaisePropertyChanged();
- }
- else
- {
- SqlSettings = new SqlSettings();
- }
- }
Meine Hauptview ist folgende:
XML-Quellcode
- <Window x:Class="aixACC_Sonepar_Import.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local="clr-namespace:aixACC_Sonepar_Import"
- xmlns:VM="clr-namespace:aixACC_Sonepar_Import.ViewModels;assembly=aixACC_Sonepar_Import.ViewModels"
- xmlns:Views="clr-namespace:aixACC_Sonepar_Import.Views"
- xmlns:Shared="clr-namespace:aixACC_Sonepar_Import.Shared;assembly=aixACC_Sonepar_Import.Shared"
- mc:Ignorable="d"
- Title="Sonepar Bestellimport" Height="450" Width="800">
- <Window.DataContext>
- <VM:MainWindowViewModel />
- </Window.DataContext>
- <Window.Resources>
- <DataTemplate DataType="{x:Type VM:SqlViewModel}">
- <Views:Sql />
- </DataTemplate>
- <DataTemplate DataType="{x:Type VM:FtpViewModel}">
- <Views:Ftp />
- </DataTemplate>
- </Window.Resources>
- <DockPanel>
- <Menu DockPanel.Dock="Top">
- <MenuItem Header="Übersicht" Command="{Binding Path=NavigateCommand}" CommandParameter="{x:Static Shared:Navigate.Übersicht}" />
- <MenuItem Header="Einstellungen">
- <MenuItem Header="SQL-Verbindung" Command="{Binding Path=NavigateCommand}" CommandParameter="{x:Static Shared:Navigate.Sql}" />
- <MenuItem Header="FTP-Verbindung" Command="{Binding Path=NavigateCommand}" CommandParameter="{x:Static Shared:Navigate.Ftp}"/>
- </MenuItem>
- </Menu>
- <ContentControl Content="{Binding Path=CurrentViewModel}" />
- </DockPanel>
- </Window>
Ich bin da aktuell ein wenig überfragt, warum genau meine Viewmodels zweimal erzeugt werden.
Über jeden Tipp bin ich dankbar!