Mvvm 如何在Windows Universal App 10中将DataTemplate设置为页面资源中的ContentControl?
如何将DataTemplate设置为PageResource中的ContentControl?我想在我的ContentControl中显示一个UserControl,并且我想像使用导航区域一样使用ContentControl。因此,它可以更改用户控件中显示的内容 我有一个Shell.xaml:Mvvm 如何在Windows Universal App 10中将DataTemplate设置为页面资源中的ContentControl?,mvvm,visual-studio-2015,uwp,Mvvm,Visual Studio 2015,Uwp,如何将DataTemplate设置为PageResource中的ContentControl?我想在我的ContentControl中显示一个UserControl,并且我想像使用导航区域一样使用ContentControl。因此,它可以更改用户控件中显示的内容 我有一个Shell.xaml: <Page x:Class="MyProject.Shell" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/present
<Page
x:Class="MyProject.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyProject"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:View="using:MyProject.View"
xmlns:ViewModel="using:MyProject.ViewModel">
<Page.DataContext>
<ViewModel:ShellViewModel />
</Page.DataContext>
<Page.Resources>
<DataTemplate>
<View:MyUserControlViewModel1 />
</DataTemplate>
<DataTemplate>
<View:MyUserControlViewModel2 />
</DataTemplate>
</Page.Resources>
<StackPanel>
<ItemsControl ItemsSource="{Binding PageViewModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ContentControl Content="{Binding CurrentPageViewModel}">
</ContentControl>
</StackPanel>
</Page>
我的Shell的视图模型是:
namespace MyProject.ShellViewModel
{
class ShellViewModel : ObservableObject
{
#region Fields
private ICommand _changePageCommand;
private IPageViewModel _currentPageViewModel;
private List<IPageViewModel> _pageViewModels;
#endregion
#region Properties / Commands
public List<IPageViewModel> PageViewModels
{
get
{
if (_pageViewModels == null)
{
_pageViewModels = new List<IPageViewModel>();
}
return _pageViewModels;
}
}
public IPageViewModel CurrentPageViewModel
{
get { return _currentPageViewModel; }
set
{
if (_currentPageViewModel != value)
{
_currentPageViewModel = value;
OnPropertyChanged("CurrentPageViewModel");
}
}
}
#endregion
#region Methods
public ShellViewModel()
{
PageViewModels.Add(new MyUserControlViewModel1());
PageViewModels.Add(new MyUserControlViewModel2());
CurrentPageViewModel = PageViewModels[0];
}
#endregion
}
}
名称空间MyProject.ShellViewModel
{
类ShellViewModel:ObserveObject
{
#区域字段
专用ICommand _changePageCommand;
私有IPageViewModel\u currentPageViewModel;
私有列表pageViewModels;
#端区
#区域属性/命令
公共列表页面视图模型
{
得到
{
如果(_pageViewModels==null)
{
_pageViewModels=新列表();
}
返回页面视图模型;
}
}
公共IPageViewModel CurrentPageViewModel
{
获取{return\u currentPageViewModel;}
设置
{
如果(_currentPageViewModel!=值)
{
_currentPageViewModel=值;
OnPropertyChanged(“CurrentPageViewModel”);
}
}
}
#端区
#区域方法
公共ShellViewModel()
{
添加(新的MyUserControlViewModel1());
添加(新的MyUserControlViewModel2());
CurrentPageViewModel=PageViewModels[0];
}
#端区
}
}
我尝试设置页面。此链接中的资源如下所示:
但是它们使用另一个名称空间,对我来说不起作用,因为我的应用程序是Windows10通用应用程序,例如DataTemplate没有数据类型属性
我正在尝试使用MVVM模式创建应用程序(如果它显然不是来自代码片段)。您可以通过创建一个派生自
DataTemplateSelector
的类来实现
在此类中,您可以重写SelectTemplateCore
方法,该方法将根据数据类型返回所需的DataTemplate
。为了使这一切更具自动魔力,您可以将每个模板的键设置为与类的名称匹配,然后使用GetType().name
搜索具有该名称的资源
为了能够在不同的级别上提供特定的实现,您可以使用VisualTreeHelper.GetParent()
沿着树向上走,直到找到匹配的资源,并使用Application.Current.Resources[typeName]
作为回退
要使用自定义模板选择器,只需将其设置为ContentControl
的ContentTemplateSelector
属性
示例
下面是一个AutoDataTemplateSelector
公共类AutoDataTemplateSelector:DataTemplateSelector
{
受保护的覆盖数据模板SelectTemplateCore(对象项)=>GetTemplateForItem(项,空);
受保护的覆盖数据模板SelectTemplateCore(对象项,DependencyObject容器)=>GetTemplateForItem(项,容器);
私有数据模板GetTemplateForItem(对象项,DependencyObject容器)
{
如果(项!=null)
{
var viewModelTypeName=item.GetType().Name;
var dataTemplateInTree=FindResourceKeyUpTree(viewModelTypeName,容器);
//返回或默认为应用程序资源
返回dataTemplateInTree???(DataTemplate)Application.Current.Resources[viewModelTypeName];
}
返回null;
}
///
///试图找到树上的资源
///
///找到的钥匙
///当前容器
///
私有数据模板FindResourceKeyUpTree(字符串resourceKey,DependencyObject容器)
{
var frameworkElement=容器作为frameworkElement;
if(frameworkElement!=null)
{
if(frameworkElement.Resources.ContainsKey(resourceKey))
{
返回frameworkElement.Resources[resourceKey]作为DataTemplate;
}
其他的
{
返回FindResourceKeyUpTree(resourceKey,VisualTreeHelper.GetParent(frameworkElement));
}
}
返回null;
}
}
现在可以将其实例化为资源,并为所使用的每种类型的ViewModel创建资源
<Application.Resources>
<local:AutoDataTemplateSelector x:Key="AutoDataTemplateSelector" />
<!-- sample viewmodel data templates -->
<DataTemplate x:Key="RedViewModel">
<Rectangle Width="100" Height="100" Fill="Red" />
</DataTemplate>
<DataTemplate x:Key="BlueViewModel">
<Rectangle Width="100" Height="100" Fill="Blue" />
</DataTemplate>
</Application.Resources>
我已经把
<Application.Resources>
<local:AutoDataTemplateSelector x:Key="AutoDataTemplateSelector" />
<!-- sample viewmodel data templates -->
<DataTemplate x:Key="RedViewModel">
<Rectangle Width="100" Height="100" Fill="Red" />
</DataTemplate>
<DataTemplate x:Key="BlueViewModel">
<Rectangle Width="100" Height="100" Fill="Blue" />
</DataTemplate>
</Application.Resources>
<ContentControl ContentTemplateSelector="{StaticResource AutoDataTemplateSelector}"
Content="{x:Bind CurrentViewModel, Mode=OneWay}" />