So habe ich eine WPF-App mit dem MVVM-Muster, das die MVVM Light-Bibliothek verwendet. Für INotifyPropertyChanged verwende ich die Fody.Weavers-Bibliothek, die bisher gut funktioniert.WPF MVVM Child ViewModel Eigenschaften nicht aktualisieren Ansicht
Ich habe eine MainWindow.xaml, die ein ContentControl hat, ihre Content-Eigenschaft ist an eine Eigenschaft in seinem Ansichtsmodell für die Navigation gebunden. Das funktioniert auch gut.
MainWindow.xaml:
<ContentControl Content="{Binding SelectedViewModel}"></ContentControl>
MainViewModel.cs
public class MainViewModel : ViewModelBase
{
// Note that Fody library handles INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public object SelectedViewModel { get; set; }
public MainViewModel()
{
SelectedViewModel = new HomeViewModel();
}
public RelayCommand<PasswordBox> AdminLoginCommand => new RelayCommand<PasswordBox>(AdminLogin);
private void AdminLogin(PasswordBox passwordBox)
{
// Login Logic...
// Does not work
SelectedViewModel = new HomeViewModel();
// Does not work either
if (SelectedViewModel is HomeViewModel)
{
((HomeViewModel)SelectedViewModel).CheckAccess();
}
// Does not work either
if (SelectedViewModel is HomeViewModel)
{
((HomeViewModel)SelectedViewModel).CanAccessTestButton = true;
}
}
}
Allerdings, wenn ich die Checkaccess-Methode auf dem SelectedViewModel nennen, direkt die CanAccessTestButton Eigenschaft von MainViewModel ändern oder setzen SelectedViewModel mit einem neuen HomeViewModel von MainViewModels AdminLogin-Methode, sie werden aktualisiert, wie ich sehe, wenn ich durch den Code gehe, aber die Bindung aktualisiert die Benutzeroberfläche nicht. Ich habe diese Methoden selbstständig ausprobiert.
Ich denke, Home.xaml nicht auf die Eigenschaft abholen, wenn vom übergeordneten Ansichtsmodell geändert. Wenn der Konstruktor von HomeViewModel beim ersten Laden initialisiert wird und sich korrekt an den Wert von CanAccessTestButton bindet, scheinen alle anderen Aufrufe von MainViewModel die Ansicht nicht zu aktualisieren.
Lustig genug, wenn ich versuche, die Eigenschaft aus dem HomeViewModel mit einem RelayCommand gebunden an eine andere Schaltfläche in Home.xaml zu ändern, funktioniert es gut.
Wie kann ich es vom Elternteil arbeiten lassen?
Home.xaml:
<Button Content="Test" IsEnabled="{Binding CanAccessTestButton}"/>
HomeViewModel.cs:
public class HomeViewModel : ViewModelBase
{
// Note that Fody library handles INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public bool CanAccessTestButton { get; set; }
public HomeViewModel()
{
OtherButtonCommand = new RelayCommand(OtherButtonClick);
CheckAccess();
}
public RelayCommand OtherButtonCommand { get; set; }
private void OtherButtonClick()
{
// WORKS!!!
CheckAccess()
}
public void CheckAccess()
{
CanAccessTestButton = AppContext.Instance.LoggedInUserHasAccess();
}
}
Edit: MVVM Licht hat eine ViewModelLocator.cs Klasse, die Sie jedes Ansichtsmodell in deklarieren müssen:
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<HomeViewModel>();
}
public MainViewModel Main => ServiceLocator.Current.GetInstance<MainViewModel>();
public HomeViewModel Home => ServiceLocator.Current.GetInstance<HomeViewModel>();
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
Dann in jedem Vie w verweisen Sie auf die Ansicht Modell, das Sie in (der Kürze halber vereinfacht Markup) binden möchten
MainWindow.xaml:
<Window DataContext="{Binding Main, Source={StaticResource Locator}}">
Home.xaml:
<UserControl DataContext="{Binding Home, Source={StaticResource Locator}}">
Beim Start HomeViewModel Konstruktor wird zweimal aufgerufen, zuerst von ViewModelLocator.cs, dann erneut von MainViewModel.cs. Vielleicht hat der ViewModelLocator den Verweis auf die Ansicht, die ich auf dem Bildschirm sehe. Irgendwelche Ideen, um zu erreichen, was ich erreichen möchte?
Sie werden nie ein PropertyChanged-Ereignis auslösen – Fabiano
Fody.Weavers behandelt dies im Hintergrund. –
Wie viele Instanzen des HomeViewModel werden erstellt? – mm8