1

In my project, I have to create an administration interface with a menu. At each click on this menu, a new tab will open. Because I am in MVVM, each tab is a different ViewModel (which inherit from the same ViewModel base class) and a different View.

I have defined an ItemTemplate for the header but it's common for all tabs instead of the content is not.

My TabControl is binded to an ObservableCollection of ViewModel base class.

So, how can I load the right view in interface according to its ViewModel?

Filburt
  • 17,626
  • 12
  • 64
  • 115
Guillaume
  • 53
  • 5
  • I'd recommend checking out this article http://msdn.microsoft.com/en-us/magazine/dd419663.aspx from Josh Smith (he's kind of an MVVM guru). In the example application, he does exactly what you are looking for. And it's a very interesting read to get into MVVM. – Gilles Radrizzi Feb 21 '11 at 15:21

2 Answers2

2

Here is my answer to a similar question where you can found an extended TabControl and an example of code.

So now I focus on your particular implementation. In this example a TabControl is bound to the Items property, a menu List - to the MenuItems property.

public class MainViewModel
{
    public MainViewModel()
    {
        MenuItems = new ObservableCollection<string>(){ "Item 1", "Item 2", "Item 3"};
        this.Items = new ObservableCollection<TabItemViewModel>
                         {
                             new TabItemViewModel("Tab 1", OnItemRequestClose),
                             new TabItemViewModel("Tab item 2", OnItemRequestClose)
                         };
    }

    public ObservableCollection<string> MenuItems { get; set; }

    public string CurrentMenuItem
    {
        get { return currentMenuItem; }
        set 
        { 
            currentMenuItem = value; 
            OnPropertyChanged("CurrentMenuItem");
            this.OnMenuChanged();
        }
    }

    public ObservableCollection<TabItemViewModel> Items { get; set; }

    public void OnItemRequestClose(TabItemViewModel item)
    {
        this.Items.Remove(item);
    }
}

XAML:

<ListBox ItemsSource="{Binding MenuItems}" 
         SelectedItem="{Binding CurrentMenuItem, Mode=TwoWay}" />

You can use a command bound to the SelectionChanged event, but my solution is more universal.

An implementation of the method OnMenuChanged:

private void OnMenuChanged()
{
    if(this.CurrentMenuItem == "Item 1")
    {
        var addItem = new TabItemViewModel("Item 1", OnItemRequestClose);
        addItem.Content = new SomeView() { DataContext = new SomeViewModel() };
        this.Items.Add(addItem);
    }
    //and so on, and so forth
}

I used this solution in a real-world application, so you can be sure that it works without problems.

Community
  • 1
  • 1
vortexwolf
  • 13,967
  • 2
  • 54
  • 72
1

Thanks for your help.

I finally solved my issue with an other way :

I use the RadTabControl (from telerik) and it exposes a property named ContentTemplateSelector which is binded to a class who extends DataTemplateSelector.

ItemsSource of RadTabControl is binded to an ObservableCollection of TabViewModelBase. At each time, i add a new tab, my DataTemplateSelector base class choose the right view according to the ViewModel.

Guillaume
  • 53
  • 5