Please enhance the close button of TabItem
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 9.6k
- Forks
- 1k
- PR merge metrics
- No merged PRs in 30d
Description
Is your feature request related to a problem? Please describe
Please implement a close button for TabItem, just like the tags on Chrome or EDGE browsers.
Describe the solution you'd like
I have implemented a close button for TabItem myself. If there is a better method, please update the functionality. This is the code I implemented myself. Firstly, add a class. Then update the style. Add Grid and place the close button in the second column.
Describe alternatives you've considered
public static class TabItemCloseBehavior
{
public static readonly DependencyProperty IsCloseButtonEnabledProperty =
DependencyProperty.RegisterAttached(
"IsCloseButtonEnabled",
typeof(bool),
typeof(TabItemCloseBehavior),
new UIPropertyMetadata(false, OnIsCloseButtonEnabledChanged));
/// <summary>Helper for getting <see cref="IsCloseButtonEnabledProperty"/> from <paramref name="obj"/>.</summary>
/// <param name="obj"><see cref="DependencyObject"/> to read <see cref="IsCloseButtonEnabledProperty"/> from.</param>
/// <returns>IsCloseButtonEnabled property value.</returns>
[AttachedPropertyBrowsableForType(typeof(DependencyObject))]
public static bool GetIsCloseButtonEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsCloseButtonEnabledProperty);
}
/// <summary>Helper for setting <see cref="IsCloseButtonEnabledProperty"/> on <paramref name="obj"/>.</summary>
/// <param name="obj"><see cref="DependencyObject"/> to set <see cref="IsCloseButtonEnabledProperty"/> on.</param>
/// <param name="value">IsCloseButtonEnabled property value.</param>
public static void SetIsCloseButtonEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsCloseButtonEnabledProperty, value);
}
private static void OnIsCloseButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TabItem tabItem && e.NewValue is bool newValue && newValue)
{
tabItem.Loaded += TabItem_Loaded;
}
}
private static void TabItem_Loaded(object sender, RoutedEventArgs e)
{
if (sender is TabItem tabItem)
{
// Manually add a close button
var closeButton = new Wpf.Ui.Controls.Button
{
Width = 16,
Height = 16,
Margin = new Thickness(8, 0, 0, 0),
Padding = new Thickness(0, 0, 0, 0),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Background = Brushes.Transparent,
BorderBrush = Brushes.Transparent,
Cursor = Cursors.Hand,
Focusable = false
};
var path = new Path
{
Data = new GeometryGroup
{
Children =
[
new LineGeometry(new Point(0, 0), new Point(8, 8)),
new LineGeometry(new Point(8, 0), new Point(0, 8))
]
},
Style = (Style)Application.Current.FindResource("CloseIconStyle"), // 使用动态资源
StrokeThickness = 1.5
};
closeButton.Content = path;
closeButton.Click += CloseButton_Click;
// Find the template root Grid for TabItem
if (tabItem.Template?.FindName("headRoot", tabItem) is Grid grid)
{
// Find the second column (position of the close button)
ColumnDefinition closeButtonColumn = grid.ColumnDefinitions[1];
// Add the button to the TabItem template and ensure it appears in the second column
Grid.SetColumn(closeButton, 1);
_ = grid.Children.Add(closeButton);
}
}
}
private static void CloseButton_Click(object sender, RoutedEventArgs e)
{
if (sender is Button button)
{
TabItem? tabItem = FindAncestor<TabItem>(button);
if (tabItem != null)
{
if (ItemsControl.ItemsControlFromItemContainer(tabItem) is System.Windows.Controls.TabControl tabControl && tabItem != null)
{
tabControl.Items.Remove(tabItem);
}
}
}
}
private static T? FindAncestor<T>(DependencyObject current)
where T : DependencyObject
{
do
{
if (current is T ancestor)
{
return ancestor;
}
current = VisualTreeHelper.GetParent(current);
}
while (current != null);
return null;
}
}
Additional context
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the TabItem control and its template, especially the headRoot Grid referenced in the proposed behavior. Compare the requested close-button appearance and interaction with the supplied implementation, then verify that a TabItem can render the button and that clicking it removes the tab from its TabControl.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- design, desktop
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100