using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace FWindSoft.Wpf.Controls { /// /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。 /// /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。 /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:WpfControl" /// /// /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。 /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:WpfControl;assembly=WpfControl" /// /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用, /// 并重新生成以避免编译错误: /// /// 在解决方案资源管理器中右击目标项目,然后依次单击 /// “添加引用”->“项目”->[浏览查找并选择此项目] /// /// /// 步骤 2) /// 继续操作并在 XAML 文件中使用控件。 /// /// /// /// public class TextBoxEditor : Control, IEditableObject { public static readonly DependencyProperty IsEditingProperty= DependencyProperty.Register("IsEditing", typeof(bool), typeof(TextBoxEditor), new PropertyMetadata(false, null)); public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(TextBoxEditor), new PropertyMetadata(null, null)); public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(TextBoxEditor), new FrameworkPropertyMetadata(null)); public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(TextBoxEditor), new FrameworkPropertyMetadata(null)); static TextBoxEditor() {//new PropertyChangedCallback(PropertyChangedCallback) DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxEditor), new FrameworkPropertyMetadata(typeof(TextBoxEditor))); } public TextBoxEditor() { //this.IsReadOnly = true; this.GotFocus += TextBoxEditor_GotFocus; this.LostFocus += TextBoxEditor_LostFocus; m_GetFocus = false; } private bool m_GetFocus; private void TextBoxEditor_GotFocus(object sender, RoutedEventArgs e) { if (this.Equals(sender)) { m_GetFocus = true; } } private void TextBoxEditor_LostFocus(object sender, RoutedEventArgs e) { if (this.Equals(sender)) { var dis = this.Dispatcher; // System.Windows.Threading.Dispatcher.CurrentDispatcher; //这个多线程有点用了 dis.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input, new Action(() => { //Thread.Sleep(1000); if (m_GetFocus) { m_GetFocus = false; } else { CancelEdit(); IsEditing = false; } })); } } protected override void OnLostFocus(RoutedEventArgs e) { //base.OnLostFocus(e); //CancelEdit(); //IsEditing = false; } /// /// 关联textBox /// public TextBox TextBox { get; private set; } public override void OnApplyTemplate() { base.OnApplyTemplate(); var btnUpdate = this.Template.FindName("BtnUpdate",this) as Button; if (btnUpdate != null) { btnUpdate.Click += BtnUpdate_Click; } var btnClear = this.Template.FindName("BtnClear", this) as Button; if (btnClear != null) { btnClear.Click += BtnClear_Click; ; } var btnComplete = this.Template.FindName("BtnComplete", this) as Button; if (btnComplete != null) { btnComplete.Click += BtnComplete_Click; ; } var textBox = this.Template.FindName("PART_ContentHost", this) as TextBox; if (textBox != null) { TextBox = textBox; } } private void BtnComplete_Click(object sender, RoutedEventArgs e) { EndEdit(); IsEditing = false; } private void BtnClear_Click(object sender, RoutedEventArgs e) { CancelEdit(); IsEditing = false; } private void BtnUpdate_Click(object sender, RoutedEventArgs e) { if (!IsEditing) { IsEditing = !IsEditing; BeginEdit(); } } #region IEditableObject 接口实现 private string TempText { get; set; } public void BeginEdit() { TempText = this.Text; TextBox.Focus(); if (this.Text != null) { TextBox.Select(this.Text.Count(), 0); } else { TextBox.Select(0, 0); } } public void EndEdit() { //只在开始编辑时设置 //TempText = this.Text; } public void CancelEdit() { this.Text = TempText; } #endregion public bool IsEditing { get { return (bool) this.GetValue(IsEditingProperty); } set { this.SetValue(IsEditingProperty, value); } } public string Text { get { return this.GetValue(TextProperty) as string; } set { this.SetValue(TextProperty, value); } } public ICommand Command { get { return (ICommand)base.GetValue(CommandProperty); } set { base.SetValue(CommandProperty, value); } } public object CommandParameter { get { return base.GetValue(CommandParameterProperty); } set { base.SetValue(CommandParameterProperty, value); } } } }