我正在尝试为 View 创建一个 DataTemplate,以根据绑定(bind)到的对象类型显示特定的 UserControl 类型(如文本框、组合框、自定义控件或其他 View )。
我有以下 MVVM 框架:
FieldView
绑定(bind)到 FieldPresenter
的实例,并且应该显示 <Textblock />
对于“Label”属性,以及用于值的 UserControl 或另一个 View (基于值的类型),其数据源设置为 Presenter 的 Value 属性。目前,我还没有完成第二部分。我不知道如何编写我需要的 WPF 模板。
View 模型:
public class FieldPresenter : Observable<object>, IFieldPresenter, INotifyPropertyChanged
{
public FieldPresenter() { }
public FieldPresenter(object value)
{
Value = value;
}
object IFieldPresenter.Value
{
get
{
return base.Value;
}
set
{
base.Value = value;
OnPropertyChanged("Value");
}
}
private string _label;
public virtual string Label
{
get
{
return _label;
}
private set
{
_label = value;
OnPropertyChanged("Label");
}
}
}
查看:
<UserControl x:Class="My.Views.FieldView"
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:ViewModels="clr-namespace:My.ViewModels"
mc:Ignorable="d"
d:DesignHeight="24" d:DesignWidth="100">
<UserControl.DataContext>
<ViewModels:FieldPresenter/>
</UserControl.DataContext>
<UserControl.Template>
<ControlTemplate>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Key" />
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,0,0" HorizontalAlignment="Stretch" Width="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualWidth}">
<TextBlock Text="{Binding Label}" FontWeight="Bold" Height="32" HorizontalAlignment="Stretch"/>
<TextBox Text="{Binding Value}" Height="Auto" HorizontalAlignment="Stretch"/>
</StackPanel>
</Grid>
</ControlTemplate>
</UserControl.Template>
</UserControl>
我很好奇我想要做的事情是否可能,或者我是否可以通过让我的 Presenter View 模型返回 UserControl 而不是对象值来解决它,并让 Presenter 从对象中解析 UserControl 类型类型,但我不觉得我的演示者应该实例化控件(或者技术上是未绑定(bind)的 View )。我应该制作一个界面,例如 IViewAs<controlType> { controlType View { get; } }
?
我还能如何替换 <TextBox Text="{Binding Value}" />
在上面的脚本中使用某种基于数据绑定(bind)对象类型的 UserControl 模板?
最佳答案
您几乎肯定需要一个 ContentTemplateSelector
:
代码:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Primitive primitive;
primitive = new Sphere();
// primitive = new Cube();
DataContext = primitive;
}
}
internal abstract class Primitive
{
public abstract string Description { get; }
}
internal class Cube : Primitive
{
public override string Description
{
get { return "Cube"; }
}
}
internal class Sphere : Primitive
{
public override string Description
{
get { return "Sphere"; }
}
}
public class MyTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var frameworkElement = container as FrameworkElement;
if (frameworkElement != null && item != null)
{
if (item is Cube)
{
return frameworkElement.FindResource("CubeTemplate") as DataTemplate;
}
if (item is Sphere)
{
return frameworkElement.FindResource("SphereTemplate") as DataTemplate;
}
}
return base.SelectTemplate(item, container);
}
}
}
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="Window"
Title="MainWindow"
Width="525"
Height="350"
mc:Ignorable="d">
<Grid>
<Grid.Resources>
<local:MyTemplateSelector x:Key="myTemplateSelector" />
<DataTemplate x:Key="CubeTemplate" DataType="local:Cube">
<Border BorderBrush="Blue"
BorderThickness="1"
CornerRadius="5" />
</DataTemplate>
<DataTemplate x:Key="SphereTemplate" DataType="local:Sphere">
<Border BorderBrush="Red"
BorderThickness="1"
CornerRadius="50" />
</DataTemplate>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="1*" />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0"
Content="{Binding Description}"
d:DataContext="{d:DesignInstance local:Primitive}" />
<ContentControl Grid.Row="1"
Content="{Binding}"
ContentTemplateSelector="{StaticResource myTemplateSelector}" />
</Grid>
</Window>
结果:
请参阅文档了解更多信息:
https://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector(v=vs.110).aspx
关于c# - 如何根据绑定(bind)对象的类型动态更改DataTemplate?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36605639/