我有以下设置:
<ListBox ItemSource="{Binding Targets}">
<ListBox.ItemTemplate>
<DataTemplate>
<view:ViewName />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我想要实现的是根据DataContext
的{{1}}内的属性动态决定在运行时使用哪个视图。简单来说,我想用一个返回正确视图的数据绑定替换ListBox
。
我使用MEF为我的应用提供插件,可能需要提供自定义视图以在适当时显示项目。在设计时我不会知道所有可能的视图类型(它们可能是从DLL动态加载的),因此简单的<view:ViewName>
不会这样做。
我已经研究过解决方案但是空洞了。
答案 0 :(得分:2)
由于您希望根据绑定值更改模板,因此您可以使用DataTrigger
来确定ContentTemplate
ListBoxItem
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContentTemplate" Value="{StaticResource DefaultTemplate}"/>
<Style.Triggers>
<DataTrigger Property="{Binding SomeProperty}" Value="A">
<Setter Property="ContentTemplate" Value="{StaticResource TemplateA}"/>
</DataTrigger>
</Style.Triggers>
</Style>
我发现这比使用DataTemplateSelector
更好,因为如果绑定属性发生更改则会重新评估,而DataTemplateSelector
则不会。
如果要根据对象类型更改模板,可以使用隐式DataTemplates
。这些DataTemplates
定义了DataType
,但没有x:Key
,并且只要WPF尝试绘制指定类型的对象,它们就会被使用。
例如,如果您在<X.Resources>
某处
<DataTemplate DataType="{x:Type models:ActionA}">
<views:ActionAView />
</DataTemplate>
然后您可以将Model对象直接插入UI,WPF将使用您指定的模板绘制它
<ContentControl Content="{Binding SomeIActionObject}" />
<ItemsControl ItemsSource="{Binding CollectionOfIActionObjects}" />
<强>更新强>
您提到您将允许用户创建包含使用MEF导入的其他模板的模块,因此在这种情况下,最好使用IValueConverter查找{{1}内的匹配模板}}
例如,如果绑定值等于Application.Resources
,则转换器可能会在"A"
中搜索名为Application.Resources
的模板并将其返回到绑定
"TemplateA"
答案 1 :(得分:1)
使用this post中的DataTemplateManager
您可以执行以下操作:
DataTemplateManager.RegisterDataTemplate<ViewModelType1, ViewType1>();
DataTemplateManager.RegisterDataTemplate<ViewModelType2, ViewType2>();
DataTemplateManager.RegisterDataTemplate<ViewModelType3, ViewType3>();
然后你将从ListBox中删除ItemTemplate
:
<ListBox ItemSource="{Binding Targets}"/>
在ListBox ViewModel中你可以:
public void AddTargets()
{
Targets.Add(new ViewModelType1());
Targets.Add(new ViewModelType2());
Targets.Add(new ViewModelType3());
}
然后,WPF将自动使用每个DataTemplate
来呈现每个相应的ViewModel。
另请注意,您可以在显示ListBox之前随时调用DataTemplateManager.RegisterDataTemplate()
,因此理论上您可以在加载MEF部件时执行此操作。
编辑:
根据您的评论,您可以使用ContentPresenter创建单个DataTemplate,以根据ViewModel中的属性显示所选的视图:
<DataTemplate DataType="{x:Type local:TargetViewModel}">
<ContentPresenter x:Name="MainContentPresenter" Content="{Binding}" ContentTemplate="{Binding YourProperty, Converter=SomeConverter}"/>
并且在SomeConverter中你应该使用与帖子中演示的相同的技术来动态生成DataTemplate。