【问题标题】:How to use custom TabItem in a TabControl template?如何在 TabControl 模板中使用自定义 TabItem?
【发布时间】:2019-09-26 14:26:14
【问题描述】:

我在自定义控件库中有一个CustomTabItem。当我在 xaml 或代码中明确使用它时,它可以工作。当我使用绑定到ViewModel (CaliburnMicro) 而不是我的控件时,使用标准TabItem。如何在xaml中指定CustomTabItem的使用?
我试图指定DataType = "{x:Type adc:ActorTabItem}" - 没有用。

我试图指定DataType="{x:Type adc:CustomTabItem}" - 没有用。

        <adc:TabControl ItemsSource="{Binding Pages}" Grid.Row="1">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"></TextBlock>
                </DataTemplate>
            </TabControl.ItemTemplate>

            <adc:TabControl.ContentTemplate>
                <DataTemplate>
                    <ContentControl cal:View.Model="{Binding}" />
                </DataTemplate>
            </adc:TabControl.ContentTemplate>
        </adc:TabControl>

【问题讨论】:

  • 您可能需要继承 TabControl 并覆盖其 ItemContainerGenerator property,以返回您自己的 ItemContainerGenerator 对象,该对象创建您的子类的实例。不幸的是,WPF 似乎没有提供一种在不继承父类的情况下插入它的方法(ListBox、ItemsControl 等也是如此)。
  • 谢谢。考虑 ItemContainerGenerator 属性的内部以及方法 ContainerFromItem (Object) 和 ContainerFromIndex (Int32)。里面有一个通用的机制,没有引用 TabItem 类。变化没有变成这个属性。这条路径将我引向 TabControl 类的 GetContainerForItemOverride 和 IsItemItsOwnContainerOverride 方法。我在子类中重新定义了这些方法,并收到了肯定的结果。下面是代码:
  • protected override bool IsItemItsOwnContainerOverride(object item) { return (item is ActorTabItem); } 受保护的覆盖 DependencyObject GetContainerForItemOverride() { return new ActorTabItem(); }
  • 接下来,我遇到了另一个问题,我的 CustomTabItem 没有父级,而 TabControl 的子级(项目)有一个视图模型。但如果我不决定,那就是另一个问题了。
  • 1) 请将您的课程添加到您的问题中,这样我就可以弄清楚父母的事情是什么。 2) 拥有视图模型的孩子根本不应该成为问题(this issue that you may not have run into yet 除外)。为什么你认为视图模型是个问题?

标签: c# wpf mvvm custom-controls caliburn.micro


【解决方案1】:

这里发生了两件事:

  1. 您需要继承 TabControl 并覆盖其 ItemContainerGenerator 属性以生成您的 MyTabItem 类型而不是它自己的类型。不幸的是,如果没有子类化,你就无法做到这一点。物品本身与ItemsPanelTempalate 没有什么相似之处。

  2. 如果您将TabControl.ItemsSource 绑定到一个集合,重新排序选项卡控件中的子项的方法是重新排序绑定的集合,然后让TabControl 处理更新UI。实际的集合必须是 ObservableCollection 才能正常工作,但无论如何都应该如此。 TabControl.ItemsSource 的声明类型是 System.Collections.IEnumerable,但您可以在您的 drop 处理程序中将其转换为 System.Collections.IList,并使用它来重新排序集合。它会起作用,并且会发出适当的通知。

【讨论】:

    【解决方案2】:

    你可以轻松地做你想做的事。只需覆盖GetContainerForItemOverride 方法如下

    public class TabControlEx : TabControl
    {
    
        protected override DependencyObject GetContainerForItemOverride()
        {
            return new TabItemEx();
        }
    }
    

    【讨论】:

    • 是的,我做到了,而且成功了。为了完整起见,我还重新定义了lang-csharp protected override bool IsItemItsOwnContainerOverride(object item) =&gt; item is TabItemEx;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 2018-04-21
    • 2011-01-28
    相关资源
    最近更新 更多