Reputation: 484
Suppose I have a usercontrol as below.
<UserControl
x:Class="MyApp.Controls.MyList"
xmlns:local="using:MyApp.Controls"
xmlns:viewModels="using:MyApp.ViewModels"
>
<UserControl.Resources>
<viewModels:CustomerViewModel x:Key="ViewModel"/>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{StaticResource ResourceKey=ViewModel}" />
</UserControl.DataContext>
<UserControl.Content>
<ListView ItemsSource={Binding ItemList} />
</UserControl.Content>
</UserControl>
I'm using this control in a Page:
<Page
x:Class="MyApp.Views.CustomerPage"
xmlns:control="using:MyApp.Controls">
<controls:MyList />
</Page>
So far so good.
Now I'd like to re-use this same control for other ViewModels. My CustomerViewModel, like all my viewmodel is inherited from interface IViewModel.
What can I do to use the same control for let's say SalesOrderViewModel?
I tried the following, but that throws an XamlParseException exception upon InitializeComponent():
<Page
x:Class="MyApp.Views.CustomerPage"
xmlns:control="using:MyApp.Controls">
<controls:MyList>
<controls:MyList.Resources>
<viewModels:SalesOrderViewModel x:Key="ViewModel"/>
</controls:MyList.Resources>
</controls:>
</Page>
What would be a working approach here?
Upvotes: 1
Views: 1374
Reputation: 5498
Viewmodel (just my quickie, a bit different from yours):
public class ViewModel
{
public string Value { get; set; } = "Default";
}
UserControl:
<UserControl
x:Class="App1.MyList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock Text="{Binding Value}" />
</Grid>
</UserControl>
In the page, set different DataContext
s for different Usercontrol
s:
<Page.Resources>
<local:ViewModel x:Key="ViewModel1" Value="First"/>
<local:ViewModel x:Key="ViewModel2" Value="Second"/>
</Page.Resources>
<StackPanel>
<local:MyList DataContext="{StaticResource ViewModel1}" />
<local:MyList DataContext="{StaticResource ViewModel2}" />
</StackPanel>
Upvotes: 1
Reputation: 49
You can use data templates for this. You can set the data type of a data template with your view model.
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:ImageViewModel}" >
<view:ImageView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:VideoViewModel}">
<view:VideoView/>
</DataTemplate>
</UserControl.Resources>
<UserControl x:Class="Overlay.View.ImageView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Example.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Image Source="/Assets/screenshot.png"/>
</Grid>
</UserControl>
<UserControl x:Class="Overlay.View.VideoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Example.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<MediaElement x:Name="Player" Source="./Assets/Sample_mp4.mp4"/>
</Grid>
Suppose you have a view model for your page control. This view model can have a property of type IViewModel which can be set depending on some conditions. You can bind this property to the content property of a content control or content presenter.
<ContentControl Grid.Row="0" x:Name="ctnCtrl" Content="{Binding CurrentVm}"/>
The content control will load the view depending on your selected view model.
Upvotes: 0