Reputation: 41
I have been trying to figure out these past 2 days how to switch between 2 User Controls back and forward with buttons inside those User Controls. I managed to make this happen but with the buttons outside those User Controls.
This is how my project files look
BaseCommand.cs
public class BaseCommand : ICommand
{
private Action<object> _method;
public event EventHandler CanExecuteChanged;
public BaseCommand(Action<object> method)
{
_method = method;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_method.Invoke(parameter);
}
}
MainViewModel.cs
class MainViewModel : INotifyPropertyChanged
{
public ICommand LogInCommand { get; set; }
public ICommand SetupCommand { get; set; }
private object selectedViewModel;
public object SelectedViewModel
{
get { return selectedViewModel; }
set { selectedViewModel = value; OnPropertyChanged("SelectedViewModel"); }
}
public MainViewModel()
{
LogInCommand = new BaseCommand(OpenLogIn);
SetupCommand = new BaseCommand(OpenSetup);
}
private void OpenLogIn(object obj)
{
SelectedViewModel = new LogInViewModel();
}
private void OpenSetup(object obj)
{
SelectedViewModel = new SetupViewModel();
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
MainWindow.xaml
<StackPanel>
<ContentControl Content="{Binding SelectedViewModel}"/>
<Button Content="Open LogIn" Height="24" Command="{Binding LogInCommand}"/>
<Button Content="Open Setup" Height="24" Command="{Binding SetupCommand}"/>
</StackPanel>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
LoginViewModel and SetupViewModel are empty classes and their corresponding views have a text block indicating what they are. What I want is to have instead 2 buttons in my MainWindow.xaml I want 1 in my LogInView.xaml that opens SetupView.xaml and vice versa.
App.xaml
<Application.Resources>
<DataTemplate DataType="{x:Type viewmodels:LogInViewModel}">
<views:LogInView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:SetupViewModel}">
<views:SetupView/>
</DataTemplate>
</Application.Resources>
Upvotes: 0
Views: 272
Reputation: 20670
Move "Open Setup" button to LogInView
and "Open LogIn" button to SetupView
.
In LogInViewModel
create SetupCommand
and pass the MainViewModel
in the ctor. When the button "Open Setup" is clicked and SetupCommand
is invoked then call new OpenSetup
method on the MainViewModel
.
public class LogInViewModel : INotifyPropertyChanged // etc.
{
private readonly MainViewModel mainViewModel;
public ICommand SetupCommand { get; set; }
public LogInViewModel(MainViewModel mainViewModel)
{
this.mainViewModel = mainViewModel;
SetupCommand = new BaseCommand(OpenSetup);
}
private void OpenSetup(object obj)
{
mainViewModel.OpenSetup();
}
....
}
Similar for SetupViewModel
public class SetupViewModel : INotifyPropertyChanged // etc.
{
private readonly MainViewModel mainViewModel;
public ICommand LogInCommand { get; set; }
public SetupViewModel(MainViewModel mainViewModel)
{
this.mainViewModel = mainViewModel;
LogInCommand = new BaseCommand(OpenLogIn);
}
private void OpenLogIn(object obj)
{
mainViewModel.OpenLogIn();
}
....
}
Finally, remove commands from MainViewModel
, modify OpenLogIn
and OpenSetup
methods and pass reference to the MainViewModel
when you create new instance of LogInViewModel
or SetupViewModel
.
public class MainViewModel : INotifyPropertyChanged
{
private object selectedViewModel;
public object SelectedViewModel
{
get { return selectedViewModel; }
set { selectedViewModel = value; OnPropertyChanged("SelectedViewModel"); }
}
public MainViewModel()
{
OpenLogIn();
}
public void OpenLogIn()
{
SelectedViewModel = new LogInViewModel(this);
}
public void OpenSetup()
{
SelectedViewModel = new SetupViewModel(this);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
Upvotes: 0