David Bentley
David Bentley

Reputation: 864

c# WPF MVVM TabControl with Multiple ViewModels and changing tabs

So I currently have a Window with a TabControl. The MainWindow has its own ViewModel and all the TabItems have their own ViewModels also.

I can easily change tabs from the MainWindow ViewModel through a bound SelectedIndex property. What I would like to do is change to another tab from code that runs within ANOTHER tab viewmodel. Since the Tabs are not part of the MainWindowViewModel, I am looking for a clean way to change the Tab without resorting to code behind to do it.

There are also cases, where I might need to change the tab from something such as a message prompt. I thinking my only way is to create and event and subscribe to that from MainWindowViewModel.

Upvotes: 1

Views: 2498

Answers (2)

Dave M
Dave M

Reputation: 3033

Rather than trying to bind to SelectedIndex, if the TabItems have their own view models, then you can create a property for each of those view models: IsSelected and then bind the TabItem.IsSelected property to that:

<TabItem IsSelected="{Binding IsSelected}">

This prevents the view models from needing to know the index of their corresponding TabItem, something I would argue is a detail that should be specific to the view and something the view model should not concern itself with. What if you add another TabItem or want to change the order? Now you've got changes to make in the view models for something that could be just simple change to the view.

Upvotes: 0

David Bentley
David Bentley

Reputation: 864

So I solved this with an EventAggregator.

public static class IntAggregator
{
    public static void Transmit(int data)
    {
        if (OnDataTransmitted != null)
        {
            OnDataTransmitted(data);
        }
    }

    public static Action<int> OnDataTransmitted;
}

First ViewModel sends data.

public class ModifyUsersViewModel : INotifyPropertyChanged
{
    private void change_tab(int data)
    {
        IntAggregator.Transmit(data);
    }
}

Second ViewModel receives data and then does something with it.

public class MainWindowViewModel : INotifyPropertyChanged
{
    private int _Tab_SelectedIndex = 0;
    public int Tab_SelectedIndex
    {
        get
        {
            return _Tab_SelectedIndex;
        }
        set
        {
            _Tab_SelectedIndex = value;
            OnPropertyChanged(new PropertyChangedEventArgs("Tab_SelectedIndex"));
        }
    }

    public MainWindowViewModel()
    {
        IntAggregator.OnDataTransmitted += OnDataReceived;
    }

    private void OnDataReceived(int data)
    {
        Tab_SelectedIndex = data;
    }
}

Upvotes: 2

Related Questions