我已经设置了一个通用对话框窗口,它接收一个视图模型和标题,然后根据窗口的XAML进行显示。
例如,此代码设置窗口的标题和数据上下文并显示它:
public void ShowWindow(object viewModel, string title)
{
var win = new DialogWindow()
{
Title = title,
DataContext = viewModel
};
win.Show();
}
窗口的代码隐藏不包含任何相关内容,但其内容展示器的XAML如下所示:
<ContentPresenter x:Name="DialogPresenter" Content="{Binding}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type i:IMyInterface}" >
<c:MyInterfacesControl/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
问题是datatemplate不会触发,因为传入的viewmodel是该接口的实现。但是,我希望代码检测viewmodel是否实现了该代码,并相应地使用该模板。
我已经考虑过使用转换器解决问题的一种或两种方法,例如检查某些内容是否是转换器参数的实现。
但这里有更简单的方法吗?
编辑:这与评论中建议的问题不同(编辑2:现在已经不见了);我不知道接口类型(可以传入许多不同的接口类型),而是有一个类型为object的数据上下文。
答案 0 :(得分:0)
DataTemplate
不能将类型用作接口,通常应该将它与具体类型一起使用。
如果您定义了接口
public interface IA
{
string A { get; set; }
}
实现它的具体类型:
public class AA : IA
{
public string A { get; set; }
}
当传递new A()
时,
<DataTemplate DataType="{x:Type local:IA}">
<TextBlock Text="{Binding A}" />
</DataTemplate>
相反,你会看到像
这样的东西Application.AA
您可以使用具体类型,然后一切都会有效:
<DataTemplate DataType="{x:Type local:AA}">
<TextBlock Text="{Binding A}" />
</DataTemplate>
使用接口类型的属性并绑定到它(而不是具体类型),这在this answer中有描述。
注意:您可以使用同名属性在具体类型中返回不同界面(选择数据模板的那个)。
您可以使用模板选择器。这非常简单,为数据模板提供密钥:
<DataTemplate x:Key="ia">
<TextBlock Text="{Binding A}" />
</DataTemplate>
并选择在代码中使用哪一个:
public class TemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is IA)
return (DataTemplate)((FrameworkElement)container).FindResource("ia");
return base.SelectTemplate(item, container);
}
}
ContentControl
拥有ContentTemplateSelector
属性,请勿使用ContentPresenter
。