1

I am trying to create MDI kind of functionality whereby I want to load a user control corresponding to the button clicked by user and unload the rest. Every button is associated with a userControl

enter image description here

<Button Content="Worker registration"/> //UserControl1
<Button Content="Worker recognition"/>  //UserControl2 ...and so on

<Grid x:Name="UserControlManager"/>
Shantanu Gupta
  • 20,688
  • 54
  • 182
  • 286

2 Answers2

3

Any reason not to use a tabcontrol? Like this

<TabControl>
    <TabItem Header="Control A">
        <local:ControlA/>
    </TabItem>
    <TabItem Header="Control B">
        <local:UserControlB/>
    </TabItem>
</TabControl>

Or bind all items using the ItemsSource

<TabControl ItemsSource="{Binding MyItems}"/>

There are also third party TabControls that's quite nice, like the one devcomponents provides. If a TabControl does not suffice (tons of issues I know), you could use a IValueConverter that would convert some property to a view. You could use a Mediator and/or ViewModelLocator, I love MVVM Light from Galasoft. They provide everything through nuget, and even sets up everything for you :)

Add a command for your buttons for selecting the content you want to show. And add the xaml for showing the SelectedControl.

Bad mediator / ViewmodelLocator ;) Use I.E. Galasofts instead like in this post

public class ViewModelLocator : INotifyPropertyChanged
{
    private UserControl selectedControl;
    private ObservableCollection<UserControl> controls = new ObservableCollection<UserControl>();
    public UserControl SelectedControl
    {
        get { return selectedControl; }
        set 
        {
            if (Equals(selectedControl, value)) return;
            selectedControl = value;
            OnPropertyChanged();
        }
    }
    public ObservableCollection<UserControl> Controls
    {
        get { return controls; }
        set
        {
            if (Equals(controls, value)) return;
            controls = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Hope it helps!

Cheers

Stian

Community
  • 1
  • 1
Stígandr
  • 2,874
  • 21
  • 36
  • 1
    I don't want to load all the user controls on compile time as there are many elements getting binded from database. Then why should I load them even though user may never open it. Earlier I was using TabControl and removed it due to this reason. Also, I wanted to have more flexibility in terms of UI – Shantanu Gupta Aug 27 '14 at 15:38
  • 2
    Though I didn't use ViewModel right now but I liked your solution. But you gave me an approach :) +1. I am still thinking about possible solutions. – Shantanu Gupta Aug 27 '14 at 15:51
  • 1
    Ah dynamic xaml, then you can't use UserControl, you must inherit from I.E. Grid (codebehind). That aside have a look at using a mediator or pref. a [ViewModelLocator](http://stackoverflow.com/a/14154088/2285592). – Stígandr Aug 27 '14 at 15:51
1

You can use DataTemplates to load views depending on what data (viweModel) you set

<Window.Resources>
    <ResourceDictionary>
        <DataTemplate DataType="{x:Type viewModel:ViewModel1}">
            <view:View1 />
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewModel:ViewModel2}">
            <view:View2 />
        </DataTemplate>
    </ResourceDictionary>
</Window.Resources>

Then have a ContentControl where your content will show

<Grid >
    <ContentControl Content="{Binding MyContent}" />
</Grid

Use an enumBooleanConverter (How to bind RadioButtons to an enum?) to select a enum with radiobuttons

<RadioButton GroupName="Navigation" 
         IsChecked="{Binding Path=SelectedNavigationEnum, 
                      Converter={StaticResource enumBooleanConverter},
                      ConverterParameter={x:Static viewModel:NavigationEnum.EnumValue1},
                      Mode=TwoWay}">Show View1</RadioButton>


<RadioButton GroupName="Navigation" 
         IsChecked="{Binding Path=SelectedNavigationEnum, 
                      Converter={StaticResource enumBooleanConverter},
                      ConverterParameter={x:Static viewModel:NavigationEnum.EnumValue2},
                      Mode=TwoWay}">Show View2</RadioButton>

When the SelectedNavigationEnum property is changed set the MyContent property to the selected viewModel

public NavigationEnum SelectedNavigationEnum
{
   ...
   set
   {
      ...  
      Navigate(value);

   }
}

protected void Navigate(NavigationEnum part)
{
    switch (part)
    {
        case NavigationEnum.EnumValue1:
            ShowView1();
            break;
        case NavigationEnum.EnumValue2:
            ShowView2();
        ...
    }
}

private void ShowView1()
{
    ViewModel1 viewModel = ObjectFactory.GetInstance<ViewModel1>();
    MyContent = viewModel;
}

When you set MyContent the DataTemplate will load View1 and set the viewModel as its DataContext.

Community
  • 1
  • 1
AxdorphCoder
  • 1,104
  • 2
  • 15
  • 26