You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
6.7 KiB

  1. using BPA.UIControl.Commons.KnownBoxes;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Data;
  10. using System.Windows.Documents;
  11. using System.Windows.Input;
  12. using System.Windows.Media;
  13. using System.Windows.Media.Imaging;
  14. using System.Windows.Navigation;
  15. using System.Windows.Shapes;
  16. namespace BPA.UIControl
  17. {
  18. /// <summary>
  19. /// 重命名工具
  20. /// </summary>
  21. [TemplatePart(Name = TextBoxPartName, Type = typeof(TextBox))]
  22. public class Renamer : ContentControl
  23. {
  24. /// <summary>
  25. /// 文本框名称
  26. /// </summary>
  27. public const string TextBoxPartName = "PART_TextBox";
  28. private TextBox textBox;
  29. #region commands
  30. /// <summary>
  31. /// 重命名命令
  32. /// </summary>
  33. public static RoutedCommand RenameCommand = new RoutedCommand();
  34. /// <summary>
  35. /// 重命名完成命令
  36. /// </summary>
  37. public static RoutedCommand RenameCompletedCommand = new RoutedCommand();
  38. /// <summary>
  39. /// 重命名取消命令
  40. /// </summary>
  41. public static RoutedCommand RenameCancelCommand = new RoutedCommand();
  42. #endregion commands
  43. #region events
  44. /// <summary>
  45. /// 文本改变事件
  46. /// </summary>
  47. public static readonly RoutedEvent TextChangedEvent =
  48. EventManager.RegisterRoutedEvent("TextChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<string>), typeof(Renamer));
  49. /// <summary>
  50. /// 文本改变事件
  51. /// </summary>
  52. public event RoutedPropertyChangedEventHandler<string> TextChanged
  53. {
  54. add { AddHandler(TextChangedEvent, value); }
  55. remove { RemoveHandler(TextChangedEvent, value); }
  56. }
  57. #endregion events
  58. #region properties
  59. /// <summary>
  60. /// 文本改变命令
  61. /// </summary>
  62. public static readonly DependencyProperty TextChangedCommandProperty =
  63. DependencyProperty.Register("TextChangedCommand", typeof(ICommand), typeof(Renamer), new PropertyMetadata(default(ICommand)));
  64. /// <summary>
  65. /// 文本改变命令
  66. /// </summary>
  67. public ICommand TextChangedCommand
  68. {
  69. get { return (ICommand)GetValue(TextChangedCommandProperty); }
  70. set { SetValue(TextChangedCommandProperty, value); }
  71. }
  72. /// <summary>
  73. /// 是否重命名中
  74. /// </summary>
  75. public static readonly DependencyProperty IsRenamingProperty = DependencyProperty.Register(
  76. "IsRenaming", typeof(bool), typeof(Renamer), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsRenamingChanged));
  77. /// <summary>
  78. /// 是否重命名中
  79. /// </summary>
  80. public bool IsRenaming
  81. {
  82. get { return (bool)GetValue(IsRenamingProperty); }
  83. set { SetValue(IsRenamingProperty, BooleanBoxes.Box(value)); }
  84. }
  85. /// <summary>
  86. /// 文本
  87. /// </summary>
  88. public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
  89. "Text", typeof(string), typeof(Renamer), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextChanged));
  90. /// <summary>
  91. /// 文本
  92. /// </summary>
  93. public string Text
  94. {
  95. get { return (string)GetValue(TextProperty); }
  96. set { SetValue(TextProperty, value); }
  97. }
  98. #endregion properties
  99. static Renamer()
  100. {
  101. DefaultStyleKeyProperty.OverrideMetadata(typeof(Renamer), new FrameworkPropertyMetadata(typeof(Renamer)));
  102. }
  103. /// <inheritdoc/>
  104. public override void OnApplyTemplate()
  105. {
  106. base.OnApplyTemplate();
  107. CommandBindings.Add(new CommandBinding(RenameCommand, RenameHandler));
  108. CommandBindings.Add(new CommandBinding(RenameCompletedCommand, RenameCompletedHandler));
  109. CommandBindings.Add(new CommandBinding(RenameCancelCommand, RenameCancelHandler));
  110. textBox = GetTemplateChild(TextBoxPartName) as TextBox;
  111. textBox.LostFocus += TextBox_LostFocus;
  112. var enterKeyBinding = new KeyBinding(RenameCompletedCommand, Key.Enter, ModifierKeys.None);
  113. var escKeyBinding = new KeyBinding(RenameCancelCommand, Key.Escape, ModifierKeys.None);
  114. var f2KeyBinding = new KeyBinding(RenameCommand, Key.F2, ModifierKeys.None);
  115. textBox.InputBindings.Add(enterKeyBinding);
  116. textBox.InputBindings.Add(escKeyBinding);
  117. this.InputBindings.Add(f2KeyBinding);
  118. this.PreviewMouseUp += (sender, e) =>
  119. {
  120. if (!IsRenaming)
  121. {
  122. //e.Handled = true;
  123. this.Focus();
  124. }
  125. };
  126. }
  127. private void RenameHandler(object sender, ExecutedRoutedEventArgs e)
  128. {
  129. IsRenaming = true;
  130. }
  131. private void RenameCompletedHandler(object sender, ExecutedRoutedEventArgs e)
  132. {
  133. IsRenaming = false;
  134. }
  135. private void RenameCancelHandler(object sender, ExecutedRoutedEventArgs e)
  136. {
  137. textBox.Text = Text;
  138. IsRenaming = false;
  139. }
  140. private void TextBox_LostFocus(object sender, RoutedEventArgs e)
  141. {
  142. IsRenaming = false;
  143. }
  144. private static void OnIsRenamingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  145. {
  146. var renamer = d as Renamer;
  147. if (renamer.IsRenaming)
  148. {
  149. renamer.textBox.Visibility = Visibility.Visible;
  150. renamer.textBox.Focus();
  151. renamer.textBox.SelectAll();
  152. }
  153. else
  154. {
  155. renamer.textBox.Visibility = Visibility.Collapsed;
  156. renamer.Focus();
  157. }
  158. }
  159. private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  160. {
  161. var renamer = d as Renamer;
  162. var oldString = e.OldValue == null ? string.Empty : e.OldValue.ToString();
  163. var newString = e.NewValue == null ? string.Empty : e.NewValue.ToString();
  164. var args = new RoutedPropertyChangedEventArgs<string>(oldString, newString);
  165. args.RoutedEvent = Renamer.TextChangedEvent;
  166. renamer.RaiseEvent(args);
  167. renamer.TextChangedCommand?.Execute(e.NewValue.ToString());
  168. }
  169. }
  170. }