【发布时间】:2018-09-13 07:06:07
【问题描述】:
我是 WPF 和 MVVM 的新手。我要做的是将两个不同的 DataTemplates 绑定到一个 ContentControl 中的两种不同类型的对象。每种对象对应一个DataTemplate。
这两种对象分别称为Unit和Component。它们包含不同的属性。例如,一个 Unit 有 3 个属性:Id、Name 和 Manufacture。一个组件有 3 个属性 Id、Type 和 Materials。示例代码如下:
public class Unit : INotifyPropertyChanged
{
private int _id;
private string _name;
private string _manufacture;
public int Id
{
get {return this._id}
set
{
this._id = value;
OnPropertyChanged("Id")
}
{
public string Name
{
get {return this._name}
set
{
this._id = value;
OnPropertyChanged("Name")
}
{
public string Manufacture
{
get {return this._manufacture}
set
{
this._id = value;
OnPropertyChanged("Manufacture")
}
{
public event PropertyChangedEventHandler PropertyChanged;
...
}
Component 类具有类似的结构。
在 MainWindow 的左侧,我有一个 ListBox 列出对象的名称(我以后会将其更改为 TreeView),右侧有一个 ContentControl。我希望当我选择一个对象的名称时,该对象的详细信息将显示在右侧。 MainWindow的代码如下:
<Windows.Resources>
<CollectionViewSource
Source="{Binding Source={x:Static Application.Current}, Path=UnitItems}"
x:Key="UnitDataView">
</CollectionViewSource>
<CollectionViewSource
Source="{Binding Source={x:Static Application.Current}, Path=ComponentItems}"
x:Key="ComponentDataView">
</CollectionViewSource>
<CompositeCollection x:Key="AllDataView
<CollectionContainer Collection="{Binding Source={StaticResource UnitDataView}}" />
<CollectionContainer Collection="{Binding Source={StaticResource ComponentDataView}}" />
</CompositeCollection>
<local: PartDataTemplateSelector x:Key="MyDataTemplateSelector"
UnitTemplate="{StaticResource unitTemplate}"
ComponentTemplate="{StaticResource componentTemplate}" />
</Windows.Resources>
<Grid>
<Grid.ColumnDefinition>
<ColumnDefinition>
<ColumnDefinition>
</Grid.ColumnDefinition>
<ListBox x:Name="ComponentListView" Grid.Column="0"
ItemsSource="{Binding Source={StaticResource AllDataView}}" />
<TabControl Grid.Column="1"
<TabItem Header="Basic Info">
<ContentControl x:Name="BasicInfoContent"
ContentTemplateSelector="{StaticResource MyDataTemplateSelector}"
Content="{Binding Source={StaticResource AllDataView}}">
</ContentControl>
</TabItem>
</TabControl>
</Grid>
UnitItems 和 ComponentItems 是 App.xaml.cs 中定义的两个 ObservableCollection<T> 对象。我在 App.xaml 中定义了一些 DataTemplates。示例代码如下:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..."
</ResourceDictionary.MergedDictionaries>
<DataTemplate DataType="{x:Type src:Unit}">
<!-- This template is to show the name of a unit object in the ListBox -->
</DataTemplate>
<DataTemplate DataType="{x:Type src:Component}">
<!-- This template is to show the name of a component object in the ListBox -->
</DataTemplate>
<DataTemplate x:Key="unitTemplate" DataType="{x:Type src:Unit}">
<!-- This template is to show the details of a unit object in the ContentControl -->
</DataTemplate>
<DataTemplate x:Key="componentTemplate" DataType="{x:Type src:Component}">
<!-- This template is to show the details of a component object in the ContentControl -->
</DataTemplate>
</Application.Resources>
而我的自定义 DataTemplateSelector 如下:
class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate UnitTemplate { get; set; }
public DataTemplate ComponentTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
swith (item)
{
case Unit _:
return UnitTemplate;
case Component _:
return ComponentTemplate;
}
return null;
}
}
我已经阅读了这篇文章ContentTemplateSelector并尝试了ContentTemplateSelector,但是由于我在ContentControl中使用了CompositeCollection和CollectionContainer来绑定这两种对象,所以我的DataTemplateSelector类中的item对象接收的是CompositeCollection类型,而不是Unit type 也不是 Component 类型,因此没有返回正确的模板。另外我尝试了DataType Property这篇文章中提到的方法,即为每个DataTemplate设置一个DataType属性,并将Path设置为“/”。也许我误解了它,但它也不起作用,我认为它与 ContentTemplateSelector 有同样的问题。那么有人可以帮我解决这个问题吗?
这是我第一次在 Stack Overflow 上提问。我知道我的一些描述和代码对于这个问题来说是微不足道的,但我只是不想错过任何可能与我的问题有关的细节。我为此道歉。另外,如果我的编码风格和数据结构有任何问题,请随时指出。对此,我真的非常感激。感谢您的阅读和帮助!
【问题讨论】:
-
嗨,Kenny,您的数据(所有单元和组件)在左侧列表中显示是否正确?
-
是的,他们是。实际上,我在他们的 ListBox 的 DataTemplates 中创建了一个 Border,并在 Border 中创建了一个 TextBlock,以绑定到 Unit 的名称和 Component 的类型。所以在 ListBox 中,一个 Unit 对象显示在它的名称中,一个 Component 对象显示在它的类型中。
-
好的,看看 Clemens 的回答。我想提出相同的解决方案,但他更快;)
-
它确实解决了我的问题。非常感谢!