65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 WPF TabItem 中添加关闭按钮

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (41投票s)

2010年5月27日

CPOL

4分钟阅读

viewsIcon

180034

downloadIcon

7452

本文展示了如何在 WPF TabItem 中添加关闭按钮。该关闭按钮仅在选定的选项卡上显示。

引言

在最近的一个项目中,我需要在选项卡上添加一个“关闭按钮”,类似于 Visual Studio 2010 中的那样。在尝试找到如何实现这一点时,我在 Internet 上找到了一些示例。这些示例中的许多都使用标题模板用于 TabItem,除了 XAML 或 XAML 与一些 C# 代码混合使用外,什么也没有。其他示例具有额外的功能,例如使选项卡标题具有不同的形状,这是我不需要的。虽然我确实有一个标题模板,它以某种方式按照我想要的方式工作,但它并不完美。而且,由于我对 XAML 不是很熟悉(因为我来自 WinForms 背景),我决定走另一条路。我知道可能有更简单的方法来实现这一点,但以下解决方案对我来说感觉简单明了,希望其他人也能觉得它有用。

我的选项卡有几个要求

  1. 关闭按钮应**仅**在当前选定的选项卡上显示 - **而不是**在所有选项卡上。
  2. 如果未选中选项卡,但您将鼠标悬停在选项卡上,则应显示关闭按钮。当鼠标离开该选项卡时,该按钮应再次消失。
  3. 当鼠标移动到关闭按钮(“**X**”)上时,“**X**”的颜色应变为红色,并应显示一个显示“关闭”的工具提示。当鼠标离开按钮时,“**X**”应恢复为黑色。
  4. 单击关闭按钮时,应关闭选项卡(显而易见)。
  5. 最后一个要求是我的选项卡应显示**整个**标题/描述 - 而不仅仅是其中的一部分。因此,选项卡标题的大小应该能够增长和缩小以适应标题。

为了完成此任务,我们需要创建两个项目

  1. 一个简单的 UserControl,其中包含一个 Label 和一个 Button
  2. 一个自定义 TabItem,带有一些重写的方法来处理关闭按钮的显示和隐藏。

Using the Code

我们需要创建的第一个项目是 UserControl

  1. 创建一个新的 UserControl 并将其命名为 CloseableHeader
  2. 向此控件添加一个 Label 并将其命名为 label_TabTitle
  3. 向此控件添加一个 Button 并将其命名为 button_close
  4. 将按钮的样式设置为 ToolBar.ButtonStyleKey
  5. 将按钮的 Text(内容)设置为 X

这是这个新 UserControl 的完整 XAML 代码

<UserControl x:Class="CloseableHeader"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="23" d:DesignWidth="81" Margin="0">
    <Grid>
      <Button Content="X"  Height="19" HorizontalAlignment="Right" Margin="0,3,4,0" 
          Name="button_close" VerticalAlignment="Top" Width="20" FontFamily="Courier" 
          FontWeight="Bold" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" 
          FontStretch="Normal" Visibility="Visible" 
          FontSize="14" Padding="0" ToolTip="Close"/>
      <Label Content="TabItem"  Height="23" HorizontalAlignment="Left" 
          Margin="4,1,0,0" Name="label_TabTitle" VerticalAlignment="Top" 
          FontFamily="Courier" FontSize="12" />
    </Grid>
</UserControl>

我们需要创建的第二个项目是自定义 TabItem

  1. 创建一个名为 ClosableTab 的新类,该类继承自 TabItem
  2. class ClosableTab : TabItem
    {
    }
  3. 创建构造函数。
  4. 在这里,我们将创建上面创建的新 UserControl CloseableHeader 的一个新实例。然后,我们将它分配给选项卡标题,如下所示。这意味着当显示 TabItem 时,它将在标题上显示我们的新 UserControl。这正是我们所需要的,因为它将显示一个标签和我们的关闭按钮。

    // Constructor
    public ClosableTab()
    {
        // Create an instance of the usercontrol
        closableTabHeader = new CloseableHeader();
        // Assign the usercontrol to the tab header
        this.Header = closableTabHeader;
    }
  5. 创建一个用于设置选项卡的“标题”的属性。如下所示,我们将简单地更新 UserControl 中的 Label
  6. /// <summary>
    /// Property - Set the Title of the Tab
    /// </summary>
    public string Title
    {
        set
        {
            ((CloseableHeader)this.Header).label_TabTitle.Content = value;
        }
    }
  7. 接下来,我们将进行四个重写来控制选项卡上关闭按钮的可见性。
  8. 当选择选项卡时 - 像这样显示关闭按钮

    // Override OnSelected - Show the Close Button
    protected override void OnSelected(RoutedEventArgs e)
    {
        base.OnSelected(e);
        ((CloseableHeader)this.Header).button_close.Visibility = Visibility.Visible;
    }

    取消选择选项卡时 - 像这样隐藏关闭按钮

    // Override OnUnSelected - Hide the Close Button
    protected override void OnUnselected(RoutedEventArgs e)
    {
        base.OnUnselected(e);
        ((CloseableHeader)this.Header).button_close.Visibility = Visibility.Hidden;
    }

    当鼠标悬停在选项卡上时 - 像这样显示关闭按钮

    // Override OnMouseEnter - Show the Close Button
    protected override void OnMouseEnter(MouseEventArgs e)
    {
        base.OnMouseEnter(e);
        ((CloseableHeader)this.Header).button_close.Visibility = Visibility.Visible;
    }

    当鼠标**未**悬停在选项卡上时 - 像这样隐藏关闭按钮

    // Override OnMouseLeave - Hide the Close Button (If it is NOT selected)
    protected override void OnMouseLeave(MouseEventArgs e)
    {
        base.OnMouseLeave(e);
        if (!this.IsSelected)
        {
            ((CloseableHeader)this.Header).button_close.Visibility = Visibility.Hidden;
        }
    }
  9. 接下来,我们需要处理我们新的 UserControl 的几个事件。这些事件处理程序将控制按钮上“**X**”的颜色、UserControl 的宽度(显示整个标题)以及关闭按钮的 Click 事件以关闭选项卡。

将以下代码添加到我们已经在上面创建的构造函数中

// Attach to the CloseableHeader events
// (Mouse Enter/Leave, Button Click, and Label resize)
closableTabHeader.button_close.MouseEnter += 
   new MouseEventHandler(button_close_MouseEnter);
closableTabHeader.button_close.MouseLeave += 
   new MouseEventHandler(button_close_MouseLeave);
closableTabHeader.button_close.Click += 
   new RoutedEventHandler(button_close_Click);
closableTabHeader.label_TabTitle.SizeChanged += 
   new SizeChangedEventHandler(label_TabTitle_SizeChanged);

添加以下事件处理程序

// Button MouseEnter - When the mouse is over the button - change color to Red
void button_close_MouseEnter(object sender, MouseEventArgs e)
{
    ((CloseableHeader)this.Header).button_close.Foreground = Brushes.Red;
}
// Button MouseLeave - When mouse is no longer over button - change color back to black
void button_close_MouseLeave(object sender, MouseEventArgs e)
{
    ((CloseableHeader)this.Header).button_close.Foreground = Brushes.Black;
}
// Button Close Click - Remove the Tab - (or raise
// an event indicating a "CloseTab" event has occurred)
void button_close_Click(object sender, RoutedEventArgs e)
{
    ((TabControl)this.Parent).Items.Remove(this);
}
// Label SizeChanged - When the Size of the Label changes
// (due to setting the Title) set position of button properly
void label_TabTitle_SizeChanged(object sender, SizeChangedEventArgs e)
{
    ((CloseableHeader)this.Header).button_close.Margin = new Thickness(
       ((CloseableHeader)this.Header).label_TabTitle.ActualWidth + 5, 3, 4, 0);
}

注意:在关闭按钮的 Click 事件中,我只是通过调用父级(TabControl)的 Items.Remove() 方法来关闭选项卡。这显然可以扩展为改为引发一个事件。然后,程序可以在其他地方确定单击关闭按钮时需要发生什么。为了演示的简单起见,我只是关闭选项卡。

您现在可以像这样使用这个自定义 TabItem

ClosableTab theTabItem = new ClosableTab();
theTabItem.Title = "Small title";
tabControl1.Items.Add(theTabItem);
theTabItem.Focus();

结论

总之,我们现在在选项卡上有了关闭按钮。这是通过创建一个简单的 UserControl 和一个自定义 TabItem 来完成的。这相对简单明了,并且易于扩展。

© . All rights reserved.