TextBoxEditor.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using System.Windows;
  10. using System.Windows.Controls;
  11. using System.Windows.Data;
  12. using System.Windows.Documents;
  13. using System.Windows.Input;
  14. using System.Windows.Media;
  15. using System.Windows.Media.Imaging;
  16. using System.Windows.Navigation;
  17. using System.Windows.Shapes;
  18. namespace FWindSoft.Wpf.Controls
  19. {
  20. /// <summary>
  21. /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
  22. ///
  23. /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
  24. /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
  25. /// 元素中:
  26. ///
  27. /// xmlns:MyNamespace="clr-namespace:WpfControl"
  28. ///
  29. ///
  30. /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
  31. /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
  32. /// 元素中:
  33. ///
  34. /// xmlns:MyNamespace="clr-namespace:WpfControl;assembly=WpfControl"
  35. ///
  36. /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
  37. /// 并重新生成以避免编译错误:
  38. ///
  39. /// 在解决方案资源管理器中右击目标项目,然后依次单击
  40. /// “添加引用”->“项目”->[浏览查找并选择此项目]
  41. ///
  42. ///
  43. /// 步骤 2)
  44. /// 继续操作并在 XAML 文件中使用控件。
  45. ///
  46. /// <MyNamespace:TextBoxEditor/>
  47. ///
  48. /// </summary>
  49. public class TextBoxEditor : Control, IEditableObject
  50. {
  51. public static readonly DependencyProperty IsEditingProperty= DependencyProperty.Register("IsEditing", typeof(bool), typeof(TextBoxEditor), new PropertyMetadata(false, null));
  52. public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(TextBoxEditor), new PropertyMetadata(null, null));
  53. public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(TextBoxEditor), new FrameworkPropertyMetadata(null));
  54. public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(TextBoxEditor), new FrameworkPropertyMetadata(null));
  55. static TextBoxEditor()
  56. {//new PropertyChangedCallback(PropertyChangedCallback)
  57. DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxEditor), new FrameworkPropertyMetadata(typeof(TextBoxEditor)));
  58. }
  59. public TextBoxEditor()
  60. {
  61. //this.IsReadOnly = true;
  62. this.GotFocus += TextBoxEditor_GotFocus;
  63. this.LostFocus += TextBoxEditor_LostFocus;
  64. m_GetFocus = false;
  65. }
  66. private bool m_GetFocus;
  67. private void TextBoxEditor_GotFocus(object sender, RoutedEventArgs e)
  68. {
  69. if (this.Equals(sender))
  70. {
  71. m_GetFocus = true;
  72. }
  73. }
  74. private void TextBoxEditor_LostFocus(object sender, RoutedEventArgs e)
  75. {
  76. if (this.Equals(sender))
  77. {
  78. var dis = this.Dispatcher; // System.Windows.Threading.Dispatcher.CurrentDispatcher;
  79. //这个多线程有点用了
  80. dis.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input,
  81. new Action(() =>
  82. {
  83. //Thread.Sleep(1000);
  84. if (m_GetFocus)
  85. {
  86. m_GetFocus = false;
  87. }
  88. else
  89. {
  90. CancelEdit();
  91. IsEditing = false;
  92. }
  93. }));
  94. }
  95. }
  96. protected override void OnLostFocus(RoutedEventArgs e)
  97. {
  98. //base.OnLostFocus(e);
  99. //CancelEdit();
  100. //IsEditing = false;
  101. }
  102. /// <summary>
  103. /// 关联textBox
  104. /// </summary>
  105. public TextBox TextBox { get; private set; }
  106. public override void OnApplyTemplate()
  107. {
  108. base.OnApplyTemplate();
  109. var btnUpdate = this.Template.FindName("BtnUpdate",this) as Button;
  110. if (btnUpdate != null)
  111. {
  112. btnUpdate.Click += BtnUpdate_Click;
  113. }
  114. var btnClear = this.Template.FindName("BtnClear", this) as Button;
  115. if (btnClear != null)
  116. {
  117. btnClear.Click += BtnClear_Click; ;
  118. }
  119. var btnComplete = this.Template.FindName("BtnComplete", this) as Button;
  120. if (btnComplete != null)
  121. {
  122. btnComplete.Click += BtnComplete_Click; ;
  123. }
  124. var textBox = this.Template.FindName("PART_ContentHost", this) as TextBox;
  125. if (textBox != null)
  126. {
  127. TextBox = textBox;
  128. }
  129. }
  130. private void BtnComplete_Click(object sender, RoutedEventArgs e)
  131. {
  132. EndEdit();
  133. IsEditing = false;
  134. }
  135. private void BtnClear_Click(object sender, RoutedEventArgs e)
  136. {
  137. CancelEdit();
  138. IsEditing = false;
  139. }
  140. private void BtnUpdate_Click(object sender, RoutedEventArgs e)
  141. {
  142. if (!IsEditing)
  143. {
  144. IsEditing = !IsEditing;
  145. BeginEdit();
  146. }
  147. }
  148. #region IEditableObject 接口实现
  149. private string TempText { get; set; }
  150. public void BeginEdit()
  151. {
  152. TempText = this.Text;
  153. TextBox.Focus();
  154. if (this.Text != null)
  155. {
  156. TextBox.Select(this.Text.Count(), 0);
  157. }
  158. else
  159. {
  160. TextBox.Select(0, 0);
  161. }
  162. }
  163. public void EndEdit()
  164. {
  165. //只在开始编辑时设置
  166. //TempText = this.Text;
  167. }
  168. public void CancelEdit()
  169. {
  170. this.Text = TempText;
  171. }
  172. #endregion
  173. public bool IsEditing
  174. {
  175. get { return (bool) this.GetValue(IsEditingProperty); }
  176. set { this.SetValue(IsEditingProperty, value); }
  177. }
  178. public string Text
  179. {
  180. get { return this.GetValue(TextProperty) as string; }
  181. set { this.SetValue(TextProperty, value); }
  182. }
  183. public ICommand Command
  184. {
  185. get
  186. {
  187. return (ICommand)base.GetValue(CommandProperty);
  188. }
  189. set
  190. {
  191. base.SetValue(CommandProperty, value);
  192. }
  193. }
  194. public object CommandParameter
  195. {
  196. get
  197. {
  198. return base.GetValue(CommandParameterProperty);
  199. }
  200. set
  201. {
  202. base.SetValue(CommandParameterProperty, value);
  203. }
  204. }
  205. }
  206. }