WPF:哪个解决方案?带有关闭按钮和新标签按钮的 TabControl

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25710613/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:29:03  来源:igfitidea点击:

WPF: Which solution? TabControl with close button and new tab button

c#wpftabcontrol

提问by raptorjr

I'm trying to find the best solution for a TabControl that both support a close button on each TabItem, and always show a "new tab button" as the last tab.

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

I've found some half working solutions, but i think that was for MVVM, that I'm not using. Enough to try to understand WPF =)

我找到了一些有效的解决方案,但我认为那是针对 MVVM 的,我没有使用。足以尝试了解 WPF =)

This is the best solution I've found so far: http://www.codeproject.com/Articles/493538/Add-Remove-Tabs-Dynamically-in-WPF

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

A solution that i actually understand. But the problem is that it is using the ItemsSource, and i don't want that. I want to bind the ItemsSource to my own collection without having to have special things in that collection to handle the new tab button.

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

I've been search for days now but cant find a good solution. And I'm really new to WPF, otherwise i could probably have adapted the half done solutions I've found, or make them complete. But unfortunately that is way out of my league for now.

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

Any help appreciated.

任何帮助表示赞赏。

采纳答案by dharshana jagoda

This is bit of a dirty way to achieve the Add (+) button placed next to the last TabItem without much work. You already know how to place a Delete button next to the TabItem caption so I've not included that logic here.

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

Basically the logic in this solution is

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

  1. To bind ItemsSource property to your own collection as well as the Add TabItem using a CompositeCollection.
  2. Disable selection of the Add(+) TabItem and instead perform an action to load a new tab when it is clicked/selected.
  1. 将 ItemsSource 属性绑定到您自己的集合以及使用 CompositeCollection 的 Add TabItem。
  2. 禁用 Add(+) TabItem 的选择,而是在单击/选择新选项卡时执行操作以加载新选项卡。

XAML bit

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>

The code behind

背后的代码

    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));

        }
    }

回答by James Willock

I have an open source library which supports MVVM and allows extra content, such as a button to be added into the tab strip. It is sports Chrome style tabs which can tear off.

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

http://dragablz.net

http://dragablz.net

回答by sondergard

You could make a converter which appends the Add tab. This way the collection of tabs in you viewmodel will only contain the real tabs.

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

The problem is then how to know when the Add tab is selected. You could make a TabItem behavior which executes a command when the tab is selected. Incidentally I recommended this for another question just recently, so you can take the code from there: TabItem selected behavior

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

回答by m-y

While I don't actually have the coded solution, I can give some insight on what is most likely the appropriate way to handle this in a WPF/MVVM pattern.

虽然我实际上没有编码的解决方案,但我可以对在 WPF/MVVM 模式中最有可能处理此问题的适当方法提供一些见解。

Firstly, if we break down the request it is as follows:

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

  1. You have a sequence of elements that you want to display.
  2. You want the user to be able to remove an individual element from the sequence.
  3. You want the user to be able to add a new element to the sequence.
  1. 您有一系列要显示的元素。
  2. 您希望用户能够从序列中删除单个元素。
  3. 您希望用户能够向序列添加新元素。

Additionally, since you are attempting to use a TabControl, you are also looking to get the behavior that a Selectorcontrol provides (element selection), as well as an area to display the element (content) which is selected.

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

So, if we stick to these behaviors you'll be fine, since the user interface controls can be customized in terms of look and feel.

所以,如果我们坚持这些行为,你会没事的,因为用户界面控件可以在外观和感觉方面进行自定义。



Of course, the best control for this is the TabControl, which are you already trying to use. If we use this control, it satisfies the first item.

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

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

Afterwards, you can customize each element, in your case you want to add a Buttonto each element which will execute a command to remove that element from the sequence. This will satisfy the second item.

之后,您可以自定义每个元素,在您的情况下,您希望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>

The last part is a bit more difficult, and will require you to actually have to create a custom control that inherits from the TabControlclass, add an ICommandDependencyProperty, and customize the control template so that it not only displays the TabPanel, but right next to it also displays a Buttonwhich handles the DependencyPropertyyou just created (the look and feel of the button will have to be customized as well). Doing all of this will allow you to display your own version of a TabControlwhich has a faux TabItem, which of course is your "Add" button. This is far far far easier said than done, and I wish you luck. Just remember that the TabPanelwraps onto multiple rows and can go both horizontally or vertically. Basically, this last part is not easy at all.

最后一部分有点困难,需要您实际上必须创建一个继承自TabControl该类的自定义控件,添加一个ICommandDependencyProperty,并自定义控件模板,使其不仅显示TabPanel,而且在它旁边还显示aButton处理DependencyProperty您刚刚创建的(按钮的外观和感觉也必须自定义)。完成所有这些将允许您显示您自己的 a 版本,TabControl其中包含一个 faux TabItem,这当然是您的“添加”按钮。这说起来容易做起来难,我祝你好运。请记住,TabPanel包裹到多行并且可以水平或垂直地进行。基本上,这最后一部分并不容易。