i.Dio
i.Dio

Reputation: 177

Switch between UserControls inside UserControl WPF MVVM caliburn

I need to navigate from one usercontrol to another with a button click, and i'm using two different approaches. enter image description here

Approach 1: I have a main window with some buttons that will select my "parent" user control view model, using the Navigation Controller.

    public NavigationController(MainWindowViewModel viewModel)
    {
        this.viewModel = viewModel;
    }

    public void Execute(object parameter)
    {
        string par = parameter.ToString();

        switch (par)
        {
            case "0":
                viewModel.SelectedViewModel = new ViewModel1();
                break;

            case "1":
                viewModel.SelectedViewModel = new ViewModel2();
                break;
        }
    }

XAML side (...)

  <Button Command="{Binding NavigationController}" CommandParameter="1" />
  <ContentControl Content="{Binding SelectedViewModel}" />

So far so good, and I believe this is a good tactic. But for Approach 2, where I have the proper "parent" user control selected, the button click is bound in a different way: XAML

    <Button cal:Message.Attach="ShowUserControl3()"/>

VM

    public object SelectedActionViewModel
    {
        get => _selectedActionViewModel;
        set
        {
            _selectedActionViewModel = value;
        }
    }

    public void ShowUserControl3()
    {
        _selectedActionViewModel = new VMusercontrol3();
        OnPropertyChanged(nameof(SelectedActionViewModel));
    }

And this second approach works fine.. on the first or second time i click the button. After that, the OnPropertyChanged keeps passing null and won't select the proper user control anymore. What am i missing here?

Extra question: how can I select UserControl3 from UserControl4 ?

Edit: All of the user controls inherit from a BaseViewModel, and that is where things are weird, because the propertyChanged is null

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public event EventHandler ClosingRequest;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Upvotes: 0

Views: 1139

Answers (1)

Anu Viswan
Anu Viswan

Reputation: 18155

I hope I understood your question correctly. An easier way to accomplish this would be to use the in-build support of Caliburn Micro. For example, modifying your shell view model as

public class ShellViewModel:Conductor<object>  // Replace object with your base viewmodel if any
{

        private UserControl1ViewModel _uc1Instance;
        public UserControl1ViewModel UC1Instance => _uc1Instance ?? (_uc1Instance = new UserControl1ViewModel());

        private UserControl2ViewModel _uc2Instance;
        public UserControl2ViewModel UC2Instance => _uc2Instance ?? (_uc2Instance = new UserControl2ViewModel());


        public void ActivateUserControl1()
        {
            ActivateItem(UC1Instance);
        }

        public void ActivateUserControl2()
        {
            ActivateItem(UC2Instance);
        }
}

The Conductor<T> class from Caliburn Micro enables you to handle multiple screens(Views) with only one active. You could now change your views as

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <StackPanel Orientation="Vertical">
            <Button x:Name="ActivateUserControl1" Content="Show UC 1"/>
            <Button x:Name="ActivateUserControl2" Content="Show UC 2"/>
        </StackPanel>

        <ContentControl Grid.Column="1" x:Name="ActiveItem"/>
    </Grid>

The same process could be repeated in your UserControl1 and UserControl2 for achieving Options to set UserControl3 and UserControl4.

Regarding your second question, which was about communicating between UserControl3 and UserControl4, you could make use of EventAggregators.

You can find a sample of EventAggregator in here.

Upvotes: 1

Related Questions