【问题标题】:How to close Tab with a close button in WPF?如何在 WPF 中使用关闭按钮关闭选项卡?
【发布时间】:2017-04-20 19:20:20
【问题描述】:

我正在开发一个 WPF 应用程序,它会在单击按钮时创建新选项卡。那工作正常。我很难弄清楚如何有一个关闭按钮,比如标签标题旁边的 X 并关闭选定的标签?

MainWindow.xaml

<Grid>
        <StackPanel Name="listConnections" Grid.Column="0" Background="#4682b4" Margin="0,0,0,-0.2" >
        </StackPanel>            
        <TabControl Name="tabConnections" Grid.Column="1" TabStripPlacement="Top" Margin="0,0,0.4,-0.2">
        </TabControl>
    </Grid>
</Window>

添加 Tab 方法以在单击按钮时创建新选项卡 MainWindow.xaml.cs

public void addTab(Connection connection)
{
    TabItem tab = new TabItem();
    tab.Header = connection.name;
    tabConnections.Items.Add(tab);
}

有没有简单的方法来做关闭按钮?

【问题讨论】:

  • tabConnections.Items 的类型是什么?它有Remove 方法吗?
  • 是的,确实如此。如果我创建一个closeTab 方法,是否可以关闭选定的选项卡? TabItem 类有一个 OnSelected 方法,我只是很难让 X 按钮显示在选项卡标题旁边。
  • 查看我的答案以获取关闭按钮和删除选项卡的解释和示例

标签: c# wpf xaml


【解决方案1】:

问题答案:

  1. 创建标签。

    使用stack panel 对齐文本框并水平关闭图像。检查下面的示例。

  2. 点击关闭时删除标签。

    为了关闭一个标签,在后面的代码中创建一个事件处理程序来处理点击。在这个事件处理程序中,您可以简单地使用:

    tabConnections.Items.RemoveAt(tabConnections.SelectedIndex);
    

    为什么要使用选定的索引?这是因为当您单击选项卡时,选项卡将成为选定的选项卡。在单击事件处理程序之后可以删除索引等于所选索引的选项卡。

示例:

在本例中,我为 TabControl 创建动态内容。通过使用您自己的用户控件作为内容。此外,此示例将在选项卡中提供关闭图像。所以首先创建一个 Tab 类和它背后的视图模式。

标签

// This class will be the Tab int the TabControl
public class ActionTabItem
{
    // This will be the text in the tab control
    public string Header { get; set; }
    // This will be the content of the tab control It is a UserControl whits you need to create manualy
    public UserControl Content { get; set; }
}

查看模式

/// view model for the TabControl To bind on
public class ActionTabViewModal
{
    // These Are the tabs that will be bound to the TabControl 
    public ObservableCollection<ActionTabItem> Tabs { get; set; }

    public ActionTabViewModal()
    {
        Tabs = new ObservableCollection<ActionTabItem>();
    }

    public void Populate()
    {
        // Add A tab to TabControl With a specific header and Content(UserControl)
        Tabs.Add(new ActionTabItem { Header = "UserControl 1", Content = new TestUserControl() });
        // Add A tab to TabControl With a specific header and Content(UserControl)
        Tabs.Add(new ActionTabItem { Header = "UserControl 2", Content = new TestUserControl() });
    }
}

现在我们需要创建 xaml whits 将选项卡项绑定到上面的视图模型。

  1. 将Header从Action Tab item绑定到TabControl中的TextBlock

  2. 给图像控件一个从关闭按钮图像开始的路径

  3. 将Content从Action Tab item绑定到UserControl

  4. 为标题信息使用堆栈面板并关闭图像并将其水平对齐。

    <Grid>
        <TabControl x:Name="actionTabs" DockPanel.Dock="Right" Background="White">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Height="21" Width="100">
                        <TextBlock Width="80" Text="{Binding Header}"/>
                        <Image Source="PathToFile\close.png" Width="20" Height="20" MouseDown="Image_MouseDown"/>
                    </StackPanel>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <UserControl Height="800" Width="1220" Content="{Binding Content}" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>

在后面的代码中

public partial class Window1 : Window
{
    private ActionTabViewModal vmd;

    public Window1()
    {
        InitializeComponent();
        // Initialize viewModel
        vmd  = new ActionTabViewModal();
        // Bind the xaml TabControl to view model tabs
        actionTabs.ItemsSource = vmd.Tabs;
        // Populate the view model tabs
        vmd.Populate();
    }

    private void Image_MouseDown(object sender, MouseButtonEventArgs e)
    { 
        // This event will be thrown when on a close image clicked
        vmd.Tabs.RemoveAt(actionTabs.SelectedIndex);
    }
}

结果:

【讨论】:

  • 这很好用,除了我想使用 MVVM 的命令绑定并且由于某种原因它没有触发我的命令。我只能让它在后面的代码中触发 Click 事件。
  • 对我来说,这个答案只适用于 MouseUp 而不是 MouseDown,因为否则按下按钮的选项卡尚未被选中
【解决方案2】:

这对我有用

  1. 创建用户控件
<Grid >
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Button Grid.Column="2" Content="X"  Height="19" OnClick="button_close_Click" HorizontalAlignment="Right" Margin="0,3,4,0" 
          VerticalAlignment="Top" Width="20" FontFamily="Courier" 
          FontWeight="Bold" 
          FontStretch="Normal"
          FontSize="14" Background="IndianRed"/>
        <Label Grid.ColumnSpan="2" Height="23" HorizontalAlignment="Left" 
          Margin="4,1,0,0" VerticalAlignment="Top" 
          FontFamily="Courier" FontSize="12" x:Name="NameLabel"/>
    </Grid>

2.用户控件类

public partial class CloseHeader : UserControl
    {
        MainWindow _shell;
        int _index;
        public CloseHeader(MainWindow shell, int index, string headerName)
        {
            InitializeComponent();
            _shell = shell;
            _index = index;
            NameLabel.Content = headerName;
        }

        private void button_close_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            _shell.CloseTab(_index);
        }
    }
  1. 在主窗口中

    List<int> _tabs = new List<int>();

    public void AddNewTab(HomeFunctions function)//HomeFunctions is an enum
    {
        int newIndex = tabControl.Items.Count;
        _tabs.Add(newIndex);
        switch (function)
        {
            case HomeFunctions.Settings:
                tabControl.Items.Add(new TabItem { Content = new SettingsControl(this), Width = 100, Header = new CloseHeader(this, newIndex, HomeFunctions.Settings.ToString()) });
                break;
        }
        tabControl.SelectedIndex = newIndex;
    }

    public void CloseTab(int tabId)
    {
        tabControl.Items.RemoveAt(_tabs.IndexOf(tabId));//tabControl.Items.RemoveAt(_tabs.IndexOf(tabId) + 1); if you have a non closeable tab first like i do in mine
      _tabs.Remove(tabId);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    相关资源
    最近更新 更多