2017-02-28 197 views
1

假設我想擴展我的工具箱中的所有文本框,以在發生'GotFocus'事件時特別執行某些操作。說,運行一行代碼,指示他們SelectAll();擴展控件的功能

什麼是最有效的方式,我可以加強這種行爲/處理一個事件到我的所有TextBoxes?

我只是使用TextBox作爲例子,因爲我計劃在WPF庫中的其他控件上做類似的事情。

+0

使用行爲受@ 26的17所建議的將是單向的。創建一個自定義的TextBox控件並使用這個而不是內置的TextBox控件是另一個。 – mm8

+0

@ mm8實際上,現在你提到我已經將這些控件中的一些設置爲UserControls,每個控件都有自己的位和代碼塊。我真正追求的是避免重複代碼。我可以把我想要的代碼,並將其應用於這些控件中的每一個的後面的代碼,它會工作得很好,但就像我說的,我想盡可能地避免這種重複,並有這些共同點在一個地方的指示。 – Logan

+0

您不應該將通用代碼放在UserControls中,而是放在您在所有UserControls中使用的自定義TextBox控件類中。 – mm8

回答

0

您想使用附加的行爲來完成此操作。下面是我目前用來做這件事的代碼,它涵蓋了一些古怪的邊緣案例。

public class TextBoxBehaviors 
{ 
    public static readonly DependencyProperty SelectAllOnFocusProperty = DependencyProperty.RegisterAttached("SelectAllOnFocus", typeof(bool), typeof(TextBoxBehaviors), new PropertyMetadata(false, OnSelectAllOnFocusChanged)); 

    public static DependencyProperty GetSelectAllOnFocus(TextBox element) 
    { 
     return (DependencyProperty)element.GetValue(SelectAllOnFocusProperty); 
    } 

    public static void SetSelectAllOnFocus(TextBox element, bool value) 
    { 
     element.SetValue(SelectAllOnFocusProperty, value); 
    } 

    private static void OnSelectAllOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var comboBox = d as ComboBox; 

     if (comboBox != null) 
     { 
      comboBox.Loaded += ComboBox_Loaded; 
      return; 
     } 

     var textBox = d as TextBox; 

     if (textBox == null) { return; } 

     if ((bool)e.OldValue) 
     { 
      textBox.PreviewMouseDown -= TextBox_PreviewMouseDown; 
      textBox.GotFocus -= TextBox_GotFocus; 
     } 

     if (!(bool)e.NewValue) 
      return; 

     textBox.PreviewMouseDown += TextBox_PreviewMouseDown; 
     textBox.GotFocus += TextBox_GotFocus; 
    } 

    private static void ComboBox_Loaded(object sender, RoutedEventArgs e) 
    { 
     var comboBox = sender as ComboBox; 

     var comboText = comboBox?.Template.FindName("PART_EditableTextBox", comboBox) as TextBox; 

     comboText?.SetValue(SelectAllOnFocusProperty, comboBox.GetValue(SelectAllOnFocusProperty)); 
    } 

    private static void TextBox_GotFocus(object sender, RoutedEventArgs e) 
    { 
     var textBox = sender as TextBox; 
     if (textBox == null) { return; } 

     // We need to dispatch this in case someone is changing the text during the GotFocus 
     // event. In that case, we want to select it all after they're done. 
     Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
                (Action)(() => TextBox_DoSelectAll(textBox))); 
    } 

    private static void TextBox_DoSelectAll(TextBox textBox) 
    { 
     if (!textBox.IsFocused) return; 

     textBox.CaretIndex = textBox.Text.Length; 
     textBox.SelectAll(); 
    } 


    private static void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     var textBox = sender as TextBox; 
     if (textBox == null) { return; } 

     if (textBox.IsFocused) 
      return; 

     textBox.Focus(); 
     e.Handled = true; // Prevent default TextBox behavior from deselecting text on mouse up 
    } 

}

用法:

<TextBox beh:TextBoxBehaviors.SelectAllOnFocus="True" /> 

或安放於所有文本框:

<Style TargetType="{x:Type TextBox}"> 
    <Setter Property="beh:TextBoxBehaviors.SelectAllOnFocus" /> 
</Style> 
+0

非常好,我現在開始越來越多地使用行爲,他們非常有用。 – Logan