Click here to Skip to main content
15,917,971 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi All,

I would like to ask you how could I switch between UserControls using DataTemplate and code in ViewModel? I have Two Views and each View has a ViewModel. One is for Administrator and one for an Employee. When Admin is logged it should load 'A' View, when Employee 'B' View.

I know that the best way is to use DataTemplates in XAML but how to determine to which ViewModel it should bind?

I'm not using any framework. No ViewModelLocators and any other classes or interfaces.

Thank you for any suggestions.

Best Regards
Posted

1 solution

Create an outer viewmodel, that knows if the user is an administrator or a employee, and then have that have a property that returns a viewmodel depending on the user type.

For example, let's say you have these two viewmodels right now;
C#
public class AdministratorViewmodel {
    public string Id {
        get { return Guid.NewGuid().ToString(); }
    }
}

C#
public class EmployeeViewmodel {
    public decimal Salary {
        get { return 100.0m; }
    }
}

And they have their data templates defined as;
XML
<DataTemplate DataType="{x:Type l:AdministratorViewmodel}">
    <DockPanel LastChildFill="True">
        <Label DockPanel.Dock="Top" Content="Administrator"/>
        <Grid DockPanel.Dock="Bottom">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0"  Content="Id:"/>
            <Label Grid.Column="1"  Content="{Binding Path=Id, Mode=OneWay}"/>
        </Grid>
    </DockPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type l:EmployeeViewmodel}">
    <DockPanel LastChildFill="True">
        <Label DockPanel.Dock="Top" Content="Employee"/>
        <Grid DockPanel.Dock="Bottom">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0"  Content="Salary:"/>
            <Label Grid.Column="1"  Content="{Binding Path=Salary, Mode=OneWay}"/>
        </Grid>
    </DockPanel>
</DataTemplate>


Then you can define another viewmodel;
C#
public class MainViewmodel {
    private readonly bool isAdministrator;

    public MainViewmodel(bool isAdministrator) {
        this.isAdministrator = isAdministrator;
    }

    public object Content {
        get { return isAdministrator ? (object)(new AdministratorViewmodel()) :  (object)(new EmployeeViewmodel()); }
    }
}

And set let that have a data template as well;
XML
<Window.Resources>
    <DataTemplate DataType="{x:Type l:MainViewmodel}">
        <DockPanel LastChildFill="True">
            <Label DockPanel.Dock="Top" Content="Some sort of parent container"/>
            <ContentPresenter DockPanel.Dock="Bottom" Content="{Binding Path=Content, Mode=OneWay}"/>
        </DockPanel>
    </DataTemplate>

Then, depending on the user type the MainViewmodel will return either an AdministratorViewmodel or an EmployeeViewmodel instance, and the correct data template will be picked by the content presenter;

Hope this helps,
Fredrik
 
Share this answer
 
Comments
LordVovin 18-May-15 4:28am    
Great! Thank you very very much! Appreciate!
Praveen Raghuvanshi 18-May-15 5:36am    
Nice explanation. Refer http://stackoverflow.com/questions/12823197/managing-multiple-views-viewmodels-in-a-single-contentcontrol for different approach and memory/performance comparison and use it based on your requirement.
Fredrik Bornander 18-May-15 6:45am    
If you have a scenario where the content view changes frequently and is heavy to create then, Yes, I would consider a different approach. But in this case I think the use-case is simpler so a straight forward approach like this is most likely Ok.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900