gpt4 book ai didi

mvvm - 如何在 Windows Universal App 10 的页面资源中将 DataTemplate 设置为 ContentControl?

转载 作者:行者123 更新时间:2023-12-03 10:16:05 26 4
gpt4 key购买 nike

如何将 DataTemplate 设置为 PageResource 中的 ContentControl?我想在我的 ContentControl 中显示一个 UserControl,我想像使用导航区域一样使用 ContentControl。因此它可以更改 UserControls 中显示的内容。

我有一个 Shell.xaml:

<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 的 View 模型是:

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
}
}

我尝试通过以下链接设置 Page.Resource:Window vs Page vs UserControl for WPF navigation?

<Window.Resources>
<DataTemplate DataType="{x:Type local:HomeViewModel}">
<local:HomeView /> <!-- This is a UserControl -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:ProductsViewModel}">
<local:ProductsView /> <!-- This is a UserControl -->
</DataTemplate>
</Window.Resources>

但是它们使用了另一个 namespace ,它对我不起作用,因为我的应用程序是 Windows 10 通用应用程序,并且没有 DataTemplate 的 DataType 属性。

我正在尝试使用 MVVM 模式制作我的应用程序(如果它不是来自代码片段的话)。

最佳答案

您可以通过创建一个派生自 DataTemplateSelector 的类来做到这一点.

在这个类中你可以覆盖SelectTemplateCore方法,它将返回 DataTemplate您需要基于数据类型。为了使这一切更加自动神奇,您可以设置每个模板的键以匹配类的名称,然后使用 GetType().Name 检索具有该名称的资源。 .

为了能够在不同级别提供特定的实现,您可以使用 VisualTreeHelper.GetParent() 在树上向上移动直到找到匹配的资源并使用 Application.Current.Resources[ typeName ]作为后备。

要使用自定义模板选择器,只需将其设置为 ContentTemplateSelector ContentControl 的属性(property).

示例

这里是一个 AutoDataTemplateSelector 的示例实现

public class AutoDataTemplateSelector : DataTemplateSelector
{
protected override DataTemplate SelectTemplateCore( object item ) => GetTemplateForItem( item, null );

protected override DataTemplate SelectTemplateCore( object item, DependencyObject container ) => GetTemplateForItem( item, container );

private DataTemplate GetTemplateForItem( object item, DependencyObject container )
{
if ( item != null )
{
var viewModelTypeName = item.GetType().Name;
var dataTemplateInTree = FindResourceKeyUpTree( viewModelTypeName, container );
//return or default to Application resource
return dataTemplateInTree ?? ( DataTemplate )Application.Current.Resources[ viewModelTypeName ];
}
return null;
}

/// <summary>
/// Tries to find the resources up the tree
/// </summary>
/// <param name="resourceKey">Key to find</param>
/// <param name="container">Current container</param>
/// <returns></returns>
private DataTemplate FindResourceKeyUpTree( string resourceKey, DependencyObject container )
{
var frameworkElement = container as FrameworkElement;
if ( frameworkElement != null )
{
if ( frameworkElement.Resources.ContainsKey( resourceKey ) )
{
return frameworkElement.Resources[ resourceKey ] as DataTemplate;
}
else
{
return FindResourceKeyUpTree( resourceKey, VisualTreeHelper.GetParent( frameworkElement ) );
}
}
return 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>

现在您可以将它与 ContentControl 一起使用如下:

<ContentControl ContentTemplateSelector="{StaticResource AutoDataTemplateSelector}"
Content="{x:Bind CurrentViewModel, Mode=OneWay}" />

我已经把sample solution on GitHub

关于mvvm - 如何在 Windows Universal App 10 的页面资源中将 DataTemplate 设置为 ContentControl?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39055964/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com