【问题标题】:ItemTemplateSelector binding to templated parent propertyItemTemplateSelector 绑定到模板化父属性
【发布时间】:2015-04-15 21:03:19
【问题描述】:

我有一些第 3 方控件,我正在为此控件设置模板属性。我在 ControlTemplate 中执行以下操作:

<ItemsControl ItemTemplate="{TemplateBinding ItemTemplate}"
              ItemsSource="{Binding Path=Items, RelativeSource={RelativeSource TemplatedParent}}" />

这工作正常。现在,我需要做的是在特定情况下应用 1 个附加模板。这意味着我需要使用 ItemTemplateSelector,我将在其中定义两个模板。

首先,我希望使用 ItemTemplateSelector 获得与使用 ItemTemplate 完全相同的行为(如上面的代码)。

<local:SomeTemplateSelector x:key="a"
                            DefaultTemplate="{what here}" />

相当于这一行:

ItemTemplate="{TemplateBinding ItemTemplate}"

编辑:这里有一个更详细的用法示例:

<SomeControl>
      <SomeControl.Template>
        <ControlTemplate TargetType="SomeControl">
          <SomeItemsControl ItemTemplate="{TemplateBinding ItemTemplate}"
                            ItemsSource="{Binding Path=Items, RelativeSource={RelativeSource TemplatedParent}}">
                <SomeItemsControl.ItemsPanel>
                  <ItemsPanelTemplate>
                    <WrapPanel IsItemsHost="True" />
                  </ItemsPanelTemplate>
                </SomeItemsControl.ItemsPanel>
              </SomeItemsControl>
        </ControlTemplate>
      </SomeControl.Template>
    </SomeControl>

【问题讨论】:

    标签: wpf wpf-controls datatemplate


    【解决方案1】:

    具有 x:key 的静态资源是您的默认模板,假设您的 TemplateSelector 实现了 DataTemplateSelector 并具有 PropertyCalled DefaultTemplate

    • 什么时候选择默认模板?

    这是您在 TemplateSelector 的 SelectTemplate(object item, DependencyObject container) 方法中决定的。

    这是一个例子:

    public class MainViewModel
    {
        public ObservableCollection<VMBase> Items { get; set; } = new ObservableCollection<VMBase>() { new Model1(), new Model2(), new Model3() };
    }
    
    public class SomeTemplateSelector : DataTemplateSelector
    {
        public DataTemplate Template1 { get; set; }
        public DataTemplate Template2 { get; set; }
        public DataTemplate DefaultTemplate { get; set; }
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item is Model1)
                return Template1;
            else if (item is Model2)
                return Template2;
            else
                return DefaultTemplate; //or return null if you need the default template of the control
        }
    }
    
    public class VMBase{}
    
    public class Model1 : VMBase{}
    
    public class Model2 : VMBase{}
    
    public class Model3 : VMBase{}
    

    XAML:

     <Window.Resources>
            <DataTemplate x:Key="defaultTemplate">
                <TextBlock>defaultTemplate</TextBlock>
            </DataTemplate>
            <DataTemplate x:Key="Template1">
                <TextBlock>Template1</TextBlock>
            </DataTemplate>
            <DataTemplate x:Key="Template2">
                <TextBlock>Template2</TextBlock>
            </DataTemplate>
            <local:SomeTemplateSelector x:Key="SomeTemplateSelector" DefaultTemplate="{StaticResource defaultTemplate}"
                                                                     Template1="{StaticResource Template1}"  
                                                                     Template2="{StaticResource Template2}">
    
            </local:SomeTemplateSelector>
        </Window.Resources>
        <ListBox ItemsSource="{Binding Items}" ItemTemplateSelector="{StaticResource SomeTemplateSelector}"></ListBox>
    

    如果您希望应用给定元素的默认模板,只需从 SelectTemplate 方法返回 null。

    【讨论】:

    • 正如我所说,第一步是实现与 ItemTemplate 绑定一样的确切功能。因此,让我们假设 DataTemplateSelector 将始终返回 DefaultTemplate。您能否提供一个示例 DefaultTemplate 应该是什么样子,具有与上面示例中的 ItemTemplate 相同的功能(我对 DataTemplateSelector 的代码不感兴趣)。
    • 正如我在上一条评论中所说,我对 DataTemplateSelector 的代码不感兴趣。我需要 DefaultTemplate 的代码,它将具有与我绑定到 ItemTemplate 的代码完全相同的功能。
    • @Goran 通过从 SelectTemplate 方法返回 null 获得的某些 ui 元素的默认模板
    • @Goran 如果您出于某种原因不喜欢返回 null,则将 DefaultTemplate 属性保留在 Selector 中并将其设置为 XAML,如 DefaultTemplate="{x:Null}"
    • 这不是问题的答案。如果你再次阅读这个问题,关键就在我给出的第一个代码示例中。 ItemsControl 正在从其父控件(第 3 方控件)获取 ItemTemplate。使用 ItemTemplateSelector 时,我需要将 DefaultTemplate 设置为与父控件相同的 ItemTemplate。在这种情况下,我不能使用 TemplateBinding。所以问题真的是:如何将第一个示例转换为使用 ItemTemplateSelector 而不是 ItemTemplate?我只对 xaml 代码(实际模板)感兴趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多