您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

313 行
11 KiB

  1. using BPA.UIControl.Commons.KnownBoxes;
  2. using System;
  3. using System.ComponentModel;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Controls.Primitives;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;
  11. namespace BPA.UIControl
  12. {
  13. /// <summary>
  14. /// TabControl 帮助类
  15. /// </summary>
  16. public static class TabControlHelper
  17. {
  18. #region 事件
  19. /// <summary>
  20. /// 关闭 TabItem 事件处理
  21. /// </summary>
  22. /// <param name="sender"></param>
  23. /// <param name="e"></param>
  24. public delegate void CloseTabItemRoutedEventHandler(object sender, CloseTabItemRoutedEventArgs e);
  25. /// <summary>
  26. /// 关闭 TabItem 事件
  27. /// </summary>
  28. public static readonly RoutedEvent CloseItemEvent = EventManager.RegisterRoutedEvent(
  29. "CloseItem", RoutingStrategy.Bubble, typeof(CloseTabItemRoutedEventHandler), typeof(TabControlHelper));
  30. public static void AddCloseItemHandler(DependencyObject dependencyObject, CloseTabItemRoutedEventHandler handler)
  31. {
  32. if (dependencyObject is TabControl tabControl)
  33. {
  34. tabControl.AddHandler(CloseItemEvent, handler);
  35. }
  36. }
  37. public static void RemoveCloseItemHandler(DependencyObject dependencyObject, CloseTabItemRoutedEventHandler handler)
  38. {
  39. if (dependencyObject is TabControl tabControl)
  40. {
  41. tabControl.RemoveHandler(CloseItemEvent, handler);
  42. }
  43. }
  44. /// <summary>
  45. /// 添加按钮点击事件
  46. /// </summary>
  47. public static readonly RoutedEvent AddButtonClickEvent = EventManager.RegisterRoutedEvent(
  48. "AddButtonClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TabControlHelper));
  49. public static void AddAddButtonClickHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
  50. {
  51. if (dependencyObject is TabControl tabControl)
  52. {
  53. tabControl.AddHandler(AddButtonClickEvent, handler);
  54. }
  55. }
  56. public static void RemoveAddButtonClickHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
  57. {
  58. if (dependencyObject is TabControl tabControl)
  59. {
  60. tabControl.RemoveHandler(AddButtonClickEvent, handler);
  61. }
  62. }
  63. #endregion
  64. #region 命令
  65. /// <summary>
  66. /// 添加命令
  67. /// </summary>
  68. public static readonly DependencyProperty AddCommandProperty =
  69. DependencyProperty.RegisterAttached("AddCommand", typeof(ICommand), typeof(TabControlHelper), new PropertyMetadata(null));
  70. public static ICommand GetAddCommand(DependencyObject obj)
  71. {
  72. return (ICommand)obj.GetValue(AddCommandProperty);
  73. }
  74. public static void SetAddCommand(DependencyObject obj, ICommand value)
  75. {
  76. obj.SetValue(AddCommandProperty, value);
  77. }
  78. #endregion
  79. /// <summary>
  80. /// 是否显示清除按钮
  81. /// </summary>
  82. public static readonly DependencyProperty IsClearableProperty =
  83. DependencyProperty.RegisterAttached("IsClearable", typeof(bool), typeof(TabControlHelper), new PropertyMetadata(BooleanBoxes.FalseBox, OnIsClearbleChanged));
  84. public static bool GetIsClearable(DependencyObject obj)
  85. {
  86. return (bool)obj.GetValue(IsClearableProperty);
  87. }
  88. public static void SetIsClearable(DependencyObject obj, bool value)
  89. {
  90. obj.SetValue(IsClearableProperty, BooleanBoxes.Box(value));
  91. }
  92. /// <summary>
  93. /// 是否显示添加按钮
  94. /// </summary>
  95. public static readonly DependencyProperty IsShowAddButtonProperty =
  96. DependencyProperty.RegisterAttached("IsShowAddButton", typeof(bool), typeof(TabControlHelper), new PropertyMetadata(BooleanBoxes.FalseBox, OnIsShowAddButtonChanged));
  97. /// <summary>
  98. /// Gets the is clearable.
  99. /// </summary>
  100. /// <param name="obj">The obj.</param>
  101. /// <returns>A bool.</returns>
  102. public static bool GetIsShowAddButton(DependencyObject obj)
  103. {
  104. return (bool)obj.GetValue(IsShowAddButtonProperty);
  105. }
  106. /// <summary>
  107. /// Sets the is clearable.
  108. /// </summary>
  109. /// <param name="obj">The obj.</param>
  110. /// <param name="value">If true, value.</param>
  111. public static void SetIsShowAddButton(DependencyObject obj, bool value)
  112. {
  113. obj.SetValue(IsShowAddButtonProperty, BooleanBoxes.Box(value));
  114. }
  115. private static TabControl FindTabControl(DependencyObject dependencyObject)
  116. {
  117. DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject);
  118. if (parent != null && !(parent is TabControl))
  119. {
  120. return FindTabControl(parent);
  121. }
  122. return parent != null ? (TabControl)parent : null;
  123. }
  124. private static void OnIsClearbleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  125. {
  126. if (d is TabItem tabItem)
  127. {
  128. void OnCloseButtonClicked(object sender, RoutedEventArgs args)
  129. {
  130. TabControl tabControl = FindTabControl(tabItem);
  131. IEditableCollectionView items = tabControl.Items;
  132. if (items.CanRemove)
  133. {
  134. var eventArgs = new CloseTabItemRoutedEventArgs(tabItem.DataContext, CloseItemEvent, tabItem);
  135. tabControl.RaiseEvent(eventArgs); // 触发移除事件
  136. if (!eventArgs.Cancel)
  137. {
  138. items.Remove(tabItem.DataContext); // Binding 移除方式
  139. }
  140. }
  141. else
  142. {
  143. var eventArgs = new CloseTabItemRoutedEventArgs(tabItem, CloseItemEvent, tabItem);
  144. tabControl.RaiseEvent(eventArgs); // 触发移除事件
  145. if (!eventArgs.Cancel)
  146. {
  147. tabControl.Items.Remove(tabItem); // TabItem 移除方式
  148. }
  149. }
  150. }
  151. if (tabItem.IsLoaded)
  152. {
  153. if (tabItem.Template.FindName("clearButton", tabItem) is Button clearButton)
  154. {
  155. if (GetIsClearable(tabItem))
  156. {
  157. clearButton.Click += OnCloseButtonClicked;
  158. }
  159. else
  160. {
  161. clearButton.Click -= OnCloseButtonClicked;
  162. }
  163. }
  164. }
  165. tabItem.Loaded += (sender, arg) =>
  166. {
  167. if (tabItem.Template.FindName("clearButton", tabItem) is Button clearButton)
  168. {
  169. if (GetIsClearable(tabItem))
  170. {
  171. clearButton.Click += OnCloseButtonClicked;
  172. }
  173. else
  174. {
  175. clearButton.Click -= OnCloseButtonClicked;
  176. }
  177. }
  178. };
  179. tabItem.Unloaded += (sender, arg) =>
  180. {
  181. if (tabItem.Template.FindName("clearButton", tabItem) is Button clearButton)
  182. {
  183. if (GetIsClearable(tabItem))
  184. {
  185. clearButton.Click -= OnCloseButtonClicked;
  186. }
  187. }
  188. };
  189. }
  190. }
  191. private static void OnIsShowAddButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  192. {
  193. if (d is TabControl tabControl)
  194. {
  195. void OnAddButtonClicked(object sender, RoutedEventArgs args)
  196. {
  197. var eventArgs = new RoutedEventArgs(AddButtonClickEvent, tabControl);
  198. tabControl.RaiseEvent(eventArgs);
  199. var command = GetAddCommand(tabControl);
  200. command?.Execute(null);
  201. }
  202. if (tabControl.IsLoaded)
  203. {
  204. if (tabControl.Template.FindName("PART_AddButton", tabControl) is Button addButton)
  205. {
  206. if (GetIsShowAddButton(tabControl))
  207. {
  208. addButton.Click += OnAddButtonClicked;
  209. }
  210. else
  211. {
  212. addButton.Click -= OnAddButtonClicked;
  213. }
  214. }
  215. }
  216. tabControl.Loaded += (sender, arg) =>
  217. {
  218. if (tabControl.Template.FindName("PART_AddButton", tabControl) is Button addButton)
  219. {
  220. if (GetIsShowAddButton(tabControl))
  221. {
  222. addButton.Click += OnAddButtonClicked;
  223. }
  224. else
  225. {
  226. addButton.Click -= OnAddButtonClicked;
  227. }
  228. }
  229. };
  230. tabControl.Unloaded += (sender, arg) =>
  231. {
  232. if (tabControl.Template.FindName("PART_AddButton", tabControl) is Button addButton)
  233. {
  234. if (GetIsShowAddButton(tabControl))
  235. {
  236. addButton.Click -= OnAddButtonClicked;
  237. }
  238. }
  239. };
  240. }
  241. }
  242. }
  243. /// <summary>
  244. /// 关闭 tab 子项事件
  245. /// </summary>
  246. public class CloseTabItemRoutedEventArgs : RoutedEventArgs
  247. {
  248. /// <summary>
  249. /// 是否取消关闭
  250. /// </summary>
  251. public bool Cancel { get; set; }
  252. /// <summary>
  253. /// 子项数据
  254. /// </summary>
  255. public object Item { get; }
  256. public CloseTabItemRoutedEventArgs(object item)
  257. : base()
  258. {
  259. Item = item;
  260. }
  261. public CloseTabItemRoutedEventArgs(object item, RoutedEvent routedEvent)
  262. : base(routedEvent)
  263. {
  264. Item = item;
  265. }
  266. public CloseTabItemRoutedEventArgs(object item, RoutedEvent routedEvent, object source)
  267. : base(routedEvent, source)
  268. {
  269. Item = item;
  270. }
  271. }
  272. }