我正在使用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工厂
答案 0 :(得分:5)
TabControl.ItemsSource
加上DataTemplates实际上是您要求的“模板作为工厂”解决方案,但它需要与您当前的方法略有不同。
不是编写过程代码来创建和模板TabItems并调用Items.Add,而是使用ItemsSource属性和数据绑定。这将导致WPF为ItemsSource中的每个对象创建一个TabItem。然后,您可以根据适当的标准(例如,设备属性)使用ContentTemplateSelector为此选项卡上显示的对象选择适当的模板 - 但在这种情况下,您将使用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:我把它分解成一个资源,主要是用较小的块来显示东西。)