This is my first question here, please understand. I've spent on this problem hours of digging nothing works for me, maybe somebody will explain me this strange (for me) problem? I've made my app in WPF with MVVM
I got in MainWindow.xaml with usercontrol which loads view with binding:
<UserControl Content="{Binding CurrentView}" />
MainWindow DataContext is MainViewModel, which derives from BaseViewModel, where i set and get CurrentView from and implement INotifyPropertyChanged.
First CurrentView is LoginViewModel - it loads in constructor of MainViewModel properly and set the view (Usercontrol Loginview.xaml). And I don't understand why when I change CurrentView property from this loaded LoginViewModel (it definitely changes - I checked it and NotifyPropertyChanged raises) - my view doesn't change - it's still LoginView, but should be WelcomeView. But when I change the same property with the same code from MainViewModel - my view changes properly. Somebody could point where's an error? Is it impossible to change CurrentView property from outside of MainViewModel even it's not the part of MainViemodel but another class or what? What I'm missing here?
CODE:
public class BaseViewModel : NotifyPropertyChanged
{
private object? _currentView;
public object? CurrentView
{
get { return _currentView; }
set
{
_currentView = value;
OnPropertyChanged(nameof(CurrentView));
}
}
}
public class MainViewModel : BaseViewModel
{
public LoginViewModel LoginViewModel { get; set; }
public WelcomeViewModel WelcomeViewModel { get; set; }
[..]
public ICommand LoginCommand { get; set; } //- this works
public MainViewModel()
{
LoginViewModel = new();
WelcomeViewModel = new();
CurrentView = LoginViewModel;
// COMMANDS
LoginCommand = new RelayCommand(o => DoLogin(), o => CanLogin()); // this works
}
private bool CanLogin()
{
return true;
}
private void DoLogin()
{
CurrentView = WelcomeViewModel;
}
}
public class LoginViewModel : BaseViewModel
{
[...]
public WelcomeViewModel WelcomeViewModel { get; set; }
// COMMANDS PROPERTIES
public ICommand LoginCommand { get; set; }
public LoginViewModel()
{
WelcomeViewModel = new();
LoginCommand = new RelayCommand(o => DoLogin(), o => CanLogin());
}
private bool CanLogin()
{
return true;
}
private void DoLogin()
{
MessageBox.Show("Login!"); // message box test showes
// here will be some authentication
CurrentView = WelcomeViewModel; // property CurrentView changes
// CurrentView = new MainViewModel().WelcomeViewModel; // this way also doesn't work
}
}
and finally XAML from UserControl LoginView.xaml (command runs properly, property CurrentView changes, but view remains the same:
<Button
Width="200"
Height="50"
Margin="10"
Command="{Binding LoginCommand}"
Content="Login"
FontSize="18" />
<!-- Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}},
Path=DataContext.LoginCommand}" THIS WORKS! -->
App.xaml has:
<DataTemplate DataType="{x:Type vievmodels:LoginViewModel}">
<viewscontents:LoginView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vievmodels:WelcomeViewModel}">
<viewscontents:WelcomeView/>
</DataTemplate>