Alexei
Alexei

Reputation: 41

How to switch between 2 User Controls?

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

Answers (1)

user2250152
user2250152

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

Related Questions