从祖先页面在 UserControl.Resources 中设置 ViewModel
Set ViewModel in UserControl.Resources from ancestor Page
假设我有如下用户控件。
<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>
我在页面中使用此控件:
<Page
x:Class="MyApp.Views.CustomerPage"
xmlns:control="using:MyApp.Controls">
<controls:MyList />
</Page>
到目前为止一切顺利。
现在我想为其他 ViewModel 重新使用相同的控件。我的 CustomerViewModel,就像我所有的视图模型一样,都是从接口 IViewModel 继承的。
如何使用相同的控件,比方说 SalesOrderViewModel?
我尝试了以下方法,但在 InitializeComponent() 时引发了 XamlParseException 异常:
<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>
这里的工作方法是什么?
您可以为此使用数据模板。您可以使用视图模型设置数据模板的数据类型。
<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>
假设您有一个用于页面控件的视图模型。这个视图模型可以有一个 属性 类型的 IViewModel ,它可以根据某些条件进行设置。您可以将此 属性 绑定到内容控件或内容呈现器的内容 属性。
<ContentControl Grid.Row="0" x:Name="ctnCtrl" Content="{Binding CurrentVm}"/>
内容控件将根据您选择的视图模型加载视图。
Viewmodel(只是我的速成,与你的有点不同):
public class ViewModel
{
public string Value { get; set; } = "Default";
}
用户控件:
<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>
在页面中,为不同的Usercontrol
设置不同的DataContext
:
<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>
假设我有如下用户控件。
<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>
我在页面中使用此控件:
<Page
x:Class="MyApp.Views.CustomerPage"
xmlns:control="using:MyApp.Controls">
<controls:MyList />
</Page>
到目前为止一切顺利。
现在我想为其他 ViewModel 重新使用相同的控件。我的 CustomerViewModel,就像我所有的视图模型一样,都是从接口 IViewModel 继承的。
如何使用相同的控件,比方说 SalesOrderViewModel?
我尝试了以下方法,但在 InitializeComponent() 时引发了 XamlParseException 异常:
<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>
这里的工作方法是什么?
您可以为此使用数据模板。您可以使用视图模型设置数据模板的数据类型。
<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>
假设您有一个用于页面控件的视图模型。这个视图模型可以有一个 属性 类型的 IViewModel ,它可以根据某些条件进行设置。您可以将此 属性 绑定到内容控件或内容呈现器的内容 属性。
<ContentControl Grid.Row="0" x:Name="ctnCtrl" Content="{Binding CurrentVm}"/>
内容控件将根据您选择的视图模型加载视图。
Viewmodel(只是我的速成,与你的有点不同):
public class ViewModel
{
public string Value { get; set; } = "Default";
}
用户控件:
<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>
在页面中,为不同的Usercontrol
设置不同的DataContext
:
<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>