1
votes

I'm using Galasoft MVVM Light Framework.

What I want to achieve is this: enter image description here

What I currently get is this: enter image description here

All my viewmodels are statically declared as instance fields in my MainViewModel.cs so they maintain state when swiching between windows:

    #region Viewmodels init.
    readonly static InputViewModel _inputViewModel = new InputViewModel();
    [...]
    readonly static LicensesViewModel _licensesViewModel = new LicensesViewModel();
    readonly static PricesViewModel _pricesViewModel = new PricesViewModel();
    #endregion

In my input user control i'm displaying a tabcontrol. In each tabitem i'm binding a new usercontrol as view

<UserControl>
        <DockPanel>
            <TabControl>
                <TabItem Header="Prices">
                    <local:PricesControl DataContext="{x:Type viewModels:PricesViewModel}" />
                </TabItem>
                <TabItem Header="Licenses">
                    <local:LicenseControl DataContext="{x:Type viewModels:LicensesViewModel}" />
                </TabItem>
            </TabControl>
        </DockPanel>
    </UserControl>

I'm however unable to bind the viewmodel to the view. The tabcontrol is always in the datacontext of the inputviewmodel.

Any suggestions are greatly appreciated!

1
Bind the TabControl to an collection that contains the view models and use data templates to display the controls. You need to provide the definition of your classes if you need any further help. Why are you for example instantiate the LicenceViewModel in the MainViewModel and not in the InputViewModel?mm8

1 Answers

3
votes

Don't use static fields in your MainViewModel, it's a bad design decision and makes your code not testable.

Instead, use the powerful data templating mechanism of WPF.

class MainViewModel : INotifyPropertyChanged
{
    // Note: this is just a sample.
    // You might want to inject the instances via DI
    public IEnumerable<INotifyPropertyChanged> TabItems { get; } =
        new[] { new PricesViewModel(), new LicensesViewModel() };
}

Use the data templates for your view models:

<TabControl ItemsSource="{Binding TabItems}" DisplayMemberPath="PropertyNameForTabHeader">
    <TabControl.Resources>
        <DataTemplate DataType="{x:Type viewModels:PricesViewModel}">
            <local:PricesControl/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewModels:LicensesViewModel}">
            <local:LicenseControl/>
        </DataTemplate>
    </TabControl.Resources>
</TabControl>

The DisplayMemberPath property specifies the name of the tab item's view model property to use as the tab's header.

With this approach, your design is dynamic and scalable.