WPF:哪种解决方案?带有关闭按钮和新选项卡按钮的选项卡控件

本文关键字:选项 控件 按钮 新选项 解决方案 关闭按钮 WPF | 更新日期: 2023-09-27 18:20:53

我正在尝试为TabControl找到最佳解决方案,该解决方案既支持每个TabItem上的关闭按钮,又始终显示"新选项卡按钮"作为最后一个选项卡。

我已经找到了一些半工作的解决方案,但我认为这是针对 MVVM 的,我没有使用。足以尝试理解WPF =(

这是我迄今为止找到的最佳解决方案:http://www.codeproject.com/Articles/493538/Add-Remove-Tabs-Dynamically-in-WPF

我真正理解的解决方案。但问题是它正在使用 ItemsSource,我不希望这样。我想将 ItemsSource 绑定到我自己的集合,而不必在该集合中具有特殊的东西来处理新的选项卡按钮。

我已经搜索了好几天,但找不到好的解决方案。而且我对 WPF 真的很陌生,否则我可能会改编我找到的半成品解决方案,或者使它们完整。但不幸的是,这目前远远超出了我的范围。

任何帮助表示赞赏。

WPF:哪种解决方案?带有关闭按钮和新选项卡按钮的选项卡控件

我有一个开源库,它支持 MVVM 并允许将额外的内容(例如将按钮添加到选项卡条中(。它是运动铬风格的标签,可以撕掉。

http://dragablz.net

这是一种无需太多工作即可实现放置在最后一个 TabItem 旁边的添加 (+( 按钮的肮脏方法。您已经知道如何在 TabItem 标题旁边放置"删除"按钮,因此我未在此处包含该逻辑。

基本上这个解决方案中的逻辑是

  1. 将 ItemsSource 属性绑定到您自己的集合以及 使用复合集合添加选项卡项。
  2. 禁用选择添加(+( 选项卡项,而是执行操作以在它时加载新选项卡被单击/选中。

XAML 位

    <TextBlock x:Name="HiddenItemWithDataContext" Visibility="Collapsed" />
    <TabControl x:Name="Tab1" SelectionChanged="Tab1_SelectionChanged" >
        <TabControl.ItemsSource>
            <CompositeCollection>
                <CollectionContainer Collection="{Binding DataContext.MyList, Source={x:Reference HiddenItemWithDataContext}}" />
                <TabItem Height="0" Width="0"  />
                <TabItem  Header="+" x:Name="AddTabButton"/>
            </CompositeCollection>
        </TabControl.ItemsSource>
    </TabControl>

背后的代码

    private void Tab1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.AddedItems.Contains(AddTabButton))
        {
            //Logic for adding a new item to the bound collection goes here.
            string newItem = "Item " + (MyList.Count + 1);
            MyList.Add(newItem);
            e.Handled = true;
            Dispatcher.BeginInvoke(new Action(() => Tab1.SelectedItem = newItem));
        }
    }

您可以制作一个附加"添加"选项卡的转换器。这样,视图模型中的选项卡集合将仅包含真正的选项卡。

那么问题是如何知道何时选择了"添加"选项卡。您可以创建一个 TabItem 行为,该行为在选择选项卡时执行命令。顺便说一下,我最近为另一个问题推荐了这个,所以你可以从那里获取代码:TabItem 选定行为

虽然我实际上没有编码的解决方案,但我可以深入了解在 WPF/MVVM 模式中处理此问题的适当方法。

首先,如果我们分解请求,如下所示:

  1. 您有一系列要显示的元素。
  2. 您希望用户能够从序列中删除单个元素。
  3. 您希望用户能够向序列添加新元素。

此外,由于您尝试使用 TabControl ,因此还希望获取 Selector 控件提供的行为(元素选择(,以及用于显示所选元素(内容(的区域。

因此,如果我们坚持这些行为,您将没事,因为用户界面控件可以根据外观和感觉进行自定义。


当然,最好的控制是 TabControl ,您已经在尝试使用。如果我们使用此控件,则它满足第一项。

<TabControl ItemsSource="{Binding Path=Customers}" />

之后,您可以自定义每个元素,在您的情况下,您希望为每个元素添加一个Button,这将执行命令以从序列中删除该元素。这将满足第二项。

<TabControl ...>
  <TabControl.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=CustomerId}" />
        <Button Command="{Binding Path=RemoveItemCommand, Mode=OneTime,
                          RelativeSource={RelativeSource FindAncestor,
                                          AncestorType={x:Type TabControl}}"
                CommandParameter="{Binding}" />
      </StackPanel>
    </DataTemplate>
  <TabControl.ItemTemplate>
</TabControl>

最后一部分有点困难,需要您实际必须创建一个继承自 TabControl 类的自定义控件,添加一个ICommand DependencyProperty,并自定义控件模板,以便它不仅显示TabPanel,而且在它旁边还显示一个处理您刚刚创建的DependencyPropertyButton(按钮的外观和感觉必须也可以定制(。执行所有这些操作将允许您显示自己的TabControl版本,该版本具有 假TabItem ,这当然是您的"添加"按钮。这说起来容易做起来难,祝你好运。请记住,TabPanel换行多行,可以水平或垂直。基本上,最后一部分一点也不容易。