接口数据上下文的 WPF 数据类型解析



我设置了一个通用对话框窗口,该窗口接收视图模型和标题,然后根据窗口的 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>

问题是数据模板不会触发,因为传入的视图模型是该接口的实现。但是,我希望代码检测视图模型是否实现了这一点,并相应地使用模板。

我想到了使用转换器解决问题的一两种方法,例如检查某些东西是否是转换器参数的实现。

但是这里有更简单的方法吗?

编辑:这与评论中提出的问题不同(编辑2:现在已经消失了(;我不会知道接口类型(可能会传入许多不同的接口类型(,而是使用对象类型的数据上下文。

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>

相反,你会看到类似的东西

应用.AA

解决方案 1

您可以使用具体类型,然后一切都会起作用:

<DataTemplate DataType="{x:Type local:AA}">
<TextBlock Text="{Binding A}" />
</DataTemplate>

解决方案 2

使用接口类型的属性并绑定到它(而不是具体类型(,这在本答案中描述。

注意:您可以使用相同的属性名称在具体类型中返回不同的接口(选择数据模板的接口(。

解决方案 3

您可以使用模板选择器。这真的很简单,给数据模板键:

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

ContentControlContentTemplateSelector属性,请不要为此使用ContentPresenter

最新更新