using System;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using HandyControl.Data;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
[TemplatePart(Name = OverflowButtonKey, Type = typeof(ContextMenuToggleButton))]
[TemplatePart(Name = HeaderPanelKey, Type = typeof(TabPanel))]
public class TabControl : System.Windows.Controls.TabControl
{
private const string OverflowButtonKey = "PART_OverflowButton";
private const string HeaderPanelKey = "PART_HeaderPanel";
private ContextMenuToggleButton _buttonOverflow;
private TabPanel _headerPanel;
///
/// 是否为内部操作
///
internal bool IsInternalAction;
///
/// 是否启用动画
///
public static readonly DependencyProperty IsEnableAnimationProperty = DependencyProperty.Register(
"IsEnableAnimation", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox));
///
/// 是否启用动画
///
public bool IsEnableAnimation
{
get => (bool)GetValue(IsEnableAnimationProperty);
set => SetValue(IsEnableAnimationProperty, value);
}
///
/// 是否可以拖动
///
public static readonly DependencyProperty IsDraggableProperty = DependencyProperty.Register(
"IsDraggable", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox));
///
/// 是否可以拖动
///
public bool IsDraggable
{
get => (bool)GetValue(IsDraggableProperty);
set => SetValue(IsDraggableProperty, value);
}
///
/// 是否显示关闭按钮
///
public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register(
"ShowCloseButton", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox));
///
/// 是否显示关闭按钮
///
public bool ShowCloseButton
{
get => (bool)GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
}
///
/// 是否将标签填充
///
public static readonly DependencyProperty IsEnableTabFillProperty = DependencyProperty.Register(
"IsEnableTabFill", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox));
///
/// 是否将标签填充
///
public bool IsEnableTabFill
{
get => (bool)GetValue(IsEnableTabFillProperty);
set => SetValue(IsEnableTabFillProperty, value);
}
///
/// 标签宽度
///
public static readonly DependencyProperty TabItemWidthProperty = DependencyProperty.Register(
"TabItemWidth", typeof(double), typeof(TabControl), new PropertyMetadata(200.0));
///
/// 标签宽度
///
public double TabItemWidth
{
get => (double)GetValue(TabItemWidthProperty);
set => SetValue(TabItemWidthProperty, value);
}
///
/// 标签高度
///
public static readonly DependencyProperty TabItemHeightProperty = DependencyProperty.Register(
"TabItemHeight", typeof(double), typeof(TabControl), new PropertyMetadata(30.0));
///
/// 标签高度
///
public double TabItemHeight
{
get => (double)GetValue(TabItemHeightProperty);
set => SetValue(TabItemHeightProperty, value);
}
///
/// 可见的标签数量
///
private int _itemShowCount;
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
if (_headerPanel == null)
{
IsInternalAction = false;
return;
}
if (!IsEnableTabFill)
{
_itemShowCount = (int)(ActualWidth / TabItemWidth);
_buttonOverflow.Show(Items.Count > 0 && Items.Count >= _itemShowCount);
}
if (IsInternalAction)
{
IsInternalAction = false;
return;
}
if (IsEnableAnimation)
{
_headerPanel.ClearValue(TabPanel.FluidMoveDurationProperty);
}
else
{
_headerPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
}
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (TabItem item in e.NewItems)
{
item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
item.IsSelected = true;
item.TabPanel = _headerPanel;
}
}
IsInternalAction = false;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_headerPanel = Template.FindName(HeaderPanelKey, this) as TabPanel;
if (IsEnableTabFill) return;
_buttonOverflow = Template.FindName(OverflowButtonKey, this) as ContextMenuToggleButton;
if (_buttonOverflow != null)
{
_itemShowCount = (int)(ActualWidth / TabItemWidth);
_buttonOverflow.Show(Items.Count > 0 && Items.Count >= _itemShowCount);
var menu = new ContextMenu
{
Placement = PlacementMode.Bottom,
PlacementTarget = _buttonOverflow
};
menu.Closed += (s, e) => _buttonOverflow.IsChecked = false;
_buttonOverflow.Menu = menu;
_buttonOverflow.Click += (s, e) =>
{
if (_buttonOverflow.IsChecked == true)
{
_buttonOverflow.Menu.Items.Clear();
foreach (TabItem item in Items)
{
var menuItem = new MenuItem
{
Header = item.Header,
Width = TabItemWidth,
IsChecked = item.IsSelected,
IsCheckable = true
};
menuItem.Click += delegate
{
_buttonOverflow.IsChecked = false;
var index = Items.IndexOf(item);
if (index >= _itemShowCount)
{
Items.Remove(item);
Items.Insert(0, item);
if (IsEnableAnimation)
{
_headerPanel.ClearValue(TabPanel.FluidMoveDurationProperty);
}
else
{
_headerPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
}
_headerPanel.ForceUpdate = true;
_headerPanel.Measure(new Size(_headerPanel.DesiredSize.Width, ActualHeight));
_headerPanel.ForceUpdate = false;
}
item.IsSelected = true;
};
_buttonOverflow.Menu.Items.Add(menuItem);
}
}
};
}
}
}
}