【问题标题】:How to make ItemsControl choose different templates depending on run-time type如何使 ItemsControl 根据运行时类型选择不同的模板
【发布时间】:2010-06-28 13:47:01
【问题描述】:

我有一个带有 ItemsControl 控件的 xaml 页面。 ItemsControl 绑定到作为 ObservableCollection 的 Guest。来宾集合可以有两种不同类型的对象:USGuest 和 UKGuest,它们都继承自 Guest。是否可以为 ItemsControl 制作两个(或更多)模板,并根据集合中当前项目的运行时类型自动在它们之间进行选择?

【问题讨论】:

  • 等等,你问的是在 Silverlight 中执行此操作,对吗?

标签: wpf silverlight mvvm itemscontrol


【解决方案1】:

我没有尝试过,但是您是否尝试将 ItemsSource 设置为 Guest 对象的 ObservableCollection 并为这两种类型设置 DataTemplate?

<DataTemplate DataType="{x:Type my:USGuestViewModel}">
    <my:USGuestView/>
</DataTemplate>
<DataTemplate DataType="{x:Type my:UKGuestViewModel}">
    <my:UKGuestView/>
</DataTemplate>

编辑:'my' 是您的 ViewModel 和 View 所在的命名空间的声明,因此您应该在 xaml 的开头添加类似的内容:

<UserControl x:Class="my.namespace.SuperView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:my.namespace">

我已经检查过,您不能在 ItemTemplate 属性中设置两个 DataTemplate。但是您可以在您的 UserControl 资源属性中设置它们:

<UserControl.Resources>
    <DataTemplate DataType="{x:Type my:USGuestViewModel}">
        <my:USGuestView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type my:UKGuestViewModel}">
        <my:UKGuestView/>
    </DataTemplate>
</UserControl.Resources>

【讨论】:

  • +1,这可能是最好的方法。只需将这些模板放在 ItemsControl 的资源中
  • 我在 ItemControl 的资源中添加了模板,但出现构建错误“无法识别或无法访问成员“DataType”。我有没有提到我正在从事 Silverlight 4 项目?在 Silverlight 中这一切都可以实现吗?
  • 我认为是这样,尽管 Silverlight 中不存在一些方法。我不认为是这样。我将使用更完整的代码片段编辑帖子
  • 在 Silverlight 中,DataTemplate 没有 DataType 属性。
  • 对不起,不知道。 Silverlight 用户是否有任何解决方法可以超越这一点?
【解决方案2】:

对不起,我不是故意要成为一个派对大便者而不是提供解决方案。但这是我在 Silverlight 中使用 MVVM 时遇到的最大障碍之一。

我过去做过的一件事是使用一个 UserControl,里面只有一个 ContentPresenter 作为 ItemsTemplate。 (这么多层!)在UserControl中,当DataContext发生变化时,我会从UserControl的资源中选择一个模板来使用。 (模板实际上不必在 UserControl 中,但我最喜欢这种封装。)

主页

<UserControl>

  <UserControl.Resources>
    <DataTemplate x:key="itemTemplate">
      <my:ItemView />
    </DataTemplate>
  </UserControl.Resources>

  <ItemsControl ItemTemplate="{StaticResource itemTemplate}" />
</UserControl>

ItemView.xaml:

<UserControl>
  <UserControl.Resources>
    <DataTemplate x:Key="Template1">
      <!-- Template #1 -->
    </DataTemplate>
    <DataTemplate x:Key="Template2">
      <!-- Template #2 -->
    </DataTemplate>
  </UserControl.Resources>

  <ContentPresenter Name="presenter"
                    Content="{Binding}" />

</UserControl>

ItemView.xaml.cs

...
OnDataContextChanged(...)
{
  var content = this.DataContext as MyDataType;
  DataTemplate template;
  switch (content.State) 
  {
    case State1:
      template = this.Resources["template1"] as DataTemplate;
      break;
    case State2:
      template = this.Resources["template2"] as DataTemplate;
      break;
  }
  this.presenter.ContentTemplate = template;
}
...

如果您仍在继续,请注意 Silverlight 也不像您在 WPF 中那样提供 OnDataContextChanged 方法。所以,为了涵盖这一点,看看 Jeremy Likness 在这里怎么说:

http://www.codeproject.com/Articles/38559/Silverlight-DataContext-Changed-Event.aspx

我经常使用它。谢谢,杰里米!

此外,与 WPF 在该领域为您提供的所有功能相比,这也存在一些非常严重的限制。例如,真的没有很好的方法来伪造一个 ItemContainerStyle 选择器。 (据我所知。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-31
    • 2021-07-03
    • 2013-01-18
    • 2018-01-12
    • 2022-11-10
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    相关资源
    最近更新 更多