【问题标题】:Create TabItems with differing content at runtime based on templates in WPF基于 WPF 中的模板在运行时创建具有不同内容的 TabItem
【发布时间】:2010-12-30 15:35:21
【问题描述】:

我正在使用 WPF 编写一个应用程序,其中一部分涉及为用户管理用于配置自定义内部设备的各种文件。我需要能够在同一个 TabControl 中的选项卡中操作不同类型的配置,这意味着 TabItems 的内容必须是动态生成的。我想用 ControlTemplates 来做这件事,但我还没有成功获得一个工作模板。我在我的 Window 资源中定义了一个名为“pendantConfigurationTabItemTemplate”的 ControlTemplate,我使用以下代码将模板(其中包含我需要访问的命名项目)应用到 TabItems 并将它们添加到它们的父 TabControl:

<ControlTemplate x:Key="pendantConfigurationTabItemTemplate" TargetType="TabItem">
    <StackPanel Orientation="Vertical">
        <my:PendantConfigurationFileEditor x:Name="configurationEditor"/>
        <StackPanel Style="{StaticResource defaultOkCancelButtonsContainerStyle}">
            <Button Style="{StaticResource defaultOkCancelButtonStyle}"/>
            <Button Style="{StaticResource defaultOkCancelButtonStyle}" Click="OkButton_Click"/>
        </StackPanel>
    </StackPanel>
</ControlTemplate>

后面的代码:

TabItem ConfigTab = new TabItem();

switch (ConfigFile.Device)
{
  case DeviceType.PENDANT:
{
  ControlTemplate TabTemplate = Resources["pendantConfigurationTabItemTemplate"] as ControlTemplate;

  ConfigTab.Template = TabTemplate;
  ConfigTab.ApplyTemplate();

  object Editor = TabTemplate.FindName("configurationEditor", ConfigTab);

  PendantConfigurationFileEditor ConfigFileEditor = Editor as PendantConfigurationFileEditor;

  ConfigFileEditor.PendantConfiguration = DeviceConfig;

  break;
}
default:
  /* snipped */
  return;
}

ConfigTab.Header = ConfigFile.ConfigurationName;

this.EditorTabs.Items.Add(ConfigTab);
this.EditorTabs.SelectedIndex = this.EditorTabs.Items.Count - 1;

但是,每当我运行程序时,都不会向选项卡控件添加选项卡,而是选项卡控件(似乎)被模板的内容替换或覆盖。有人可以帮我解决这个问题吗?

实际上,我想做的是使用 WPF 模板作为 TabItem 工厂

【问题讨论】:

    标签: wpf tabcontrol controltemplate tabitem


    【解决方案1】:

    TabControl.ItemsSource 加上 DataTemplates 实际上是您要求的“模板即工厂”解决方案,但它需要与您当前的方法略有不同的方法。

    与其编写程序代码来创建和模板化 TabItems 并调用 Items.Add,不如使用 ItemsSource 属性和数据绑定。这将导致 WPF 为 ItemsSource 中的每个对象创建一个 TabItem。然后,您可以使用 ContentTemplateSelector 为显示在此选项卡上的对象选择适当的模板,根据任何适当的标准(例如 Device 属性) - 尽管在这种情况下您将使用 DataTemplates 而不是 ControlTemplates。

    您的选择器将如下所示:

    public class DeviceTypeSelector : DataTemplateSelector
    {
      public DataTemplate PendantTemplate { get; set; }
      public DataTemplate DefaultTemplate { get; set; }
    
      public override SelectTemplate(object item, DependencyObject container)
      {
        ConfigFile cf = (ConfigFile)item;
        switch (cf.Device)
        {
          case DeviceType.Pendant: return PendantTemplate;
          default: return DefaultTemplate;
        }
      }
    }
    

    并将像这样在 XAML 中实例化:

    <local:DeviceTypeSelector x:Key="dts"
                              PendantTemplate="{StaticResource pt}"
                              DefaultTemplate="{StaticResource dt}" />
    

    (其中 pt 和 dt 是资源中其他地方定义的合适的 DataTemplates)。

    最后,您的 TabControl 将如下所示:

    <TabControl Name="EditorTabs"
                ContentTemplateSelector="{StaticResource dts}" />
    

    然后将其设置为 EditorTabs.ItemsSource = myConfigFiles;(或者最好让它从 DataContext 获取 XAML 中的 ItemsSource)。

    您还需要设置 TabItems 的标题:为此,请使用 TabControl.ItemContainerStyle,并为 Header 属性设置一个 Setter。我认为这看起来像这样:

    <TabControl ...>
      <TabControl.ItemContainerStyle>
        <Style TargetType="TabItem">
          <Setter Property="Header" Value="{Binding ConfigurationName}" />
        </Style>
      </TabControl.ItemContainerStyle>
    </TabControl>
    

    (顺便说一句,您也可以内联 ContentTemplateSelector:我将它分解为一个资源,主要是为了以更小的块显示内容。)

    【讨论】:

    • 这是一个很好的答案,我会试一试。但是,我认为 DataTemplates 更适合显示数据,而 ControlTemplates 旨在用作可重用控件以减少需要创建的 UserControls 的数量?我需要能够编辑选项卡中显示/数据绑定的对象
    • 别担心,DataTemplate 用于显示和编辑数据。它们绝对可以包含更新正在显示的对象的 UI 元素——只需确保 DataTemplate 中的元素绑定是双向的(这是文本框的默认设置,但不是所有控件的默认设置)。 ControlTemplates 更多的是关于在利用现有行为的同时更改控件的 UI,例如使 Button 显示为没有通常按钮镶边的独立图形,或将 TabControl 显示为轮播、rolodex 或(纸质)笔记本。
    • 您的建议奏效了,而且非常好。非常感谢,我真的很感激:)
    猜你喜欢
    • 2013-10-02
    • 2017-02-10
    • 1970-01-01
    • 2016-01-30
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 2012-02-18
    相关资源
    最近更新 更多