您不会在模板中更改模板,这不是它的工作方式。
有很多方法可以做到这一点。取决于您的应用程序的配置方式。最常用的方法是
- ContentControl 或 ItemsControl 绑定到属性/集合
- 集合包含一个或多个不同类型的实例
- 您在应用程序的资源中定义 DataTemplates,其 DataType 与您的实例类型匹配
例如,您的应用程序中有几个模型
public sealed class Foo
{
public string Text {get;set;}
}
public sealed class Bar
{
public bool Checked {get;set;}
}
您的应用程序公开了一个包含一个或多个这些实例的属性
public partial class MainWindow : Window
{
//INotifyPropertyChanged/DependencyObject stuff left out!
public object FooOrBar {get;set;}
//snip
}
在您的 XAML 中,您有一个 UIElement 类型,它扩展了ItemsControl或ContentControl或类似的可以绑定到该属性的类型。
<Window
x:Name="root"
xmlns:t="clr-namespace:MyApplicationWhereFooAndBarLive"
SkipAllThatXmlnsDefinitionNonsenseForSpaceSavingsInThisExample="true"/>
<!-- see Resources below -->
<ConentControl Content="{Binding FooOrBar, ElementName=root}" />
</Window>
最后,在应用程序的资源中为每种类型定义 DataTemplates
<Window.Resources>
<DataTemplate DataType="{x:Type t:Foo}">
<TextBox Text="{Binding Text}" />
</DataTemplate >
<DataTemplate DataType="{x:Type t:Bar}">
<CheckBox Checked="{Binding Checked}" />
</DataTemplate >
</Window.Resources>
DataTemplate 选择的过程是这样的:
- 有人在某个地方设置(我们将在这个例子中说)
FooOrBar = new Foo();
- ContentControl 的内容绑定更新(通过 INPC 或 DependencyProperty)
- ContentControl 查找其DataTemplateSelector,发现没有配置并使用默认实现。
- 默认的 DataTemplateSelector 获取绑定到 Content 属性的对象的类型。
- DataTemplateSelector(本质上)在逻辑树中查找作为 DataTemplate 并且具有与步骤 4 中标识的实例类型匹配的类型的键的资源。
- 找到 DataTemplate,并将其传递给 ConentControl
- ContentControl 通过该
LoadContent()
方法加载可视化树。
- ContentControl 将此可视化树根的 DataContext 设置为 Content 属性中的值(在我们的例子中,是 的新实例
Foo
)
- 此可视化树 (IIRC) 添加为 ConentControl 的子项,现在在 UI 中可见。
ItemsControl 的情况大致相同,只是添加了一个中介(即,ListBox 使用 ListBoxItem 作为中介,而 LBI 是一个 ContentControl)。