C# 扩展控件';s能力

C# 扩展控件';s能力,c#,.net,wpf,xaml,C#,.net,Wpf,Xaml,假设我想扩展工具箱中的所有文本框,以便在引发“GotFocus”事件时执行某些操作。 比如,运行一行代码,指示他们选择All() 我可以用什么最有效的方式将这种行为/事件处理添加到我的所有文本框中 我只是以TextBox为例,因为我计划在今后的WPF库中对其他控件执行类似的操作。您希望使用附加的行为来完成此操作。下面是我目前用来做这件事的代码,它涵盖了一些奇怪的边缘情况 public class TextBoxBehaviors { public static readonly Depe

假设我想扩展工具箱中的所有文本框,以便在引发“GotFocus”事件时执行某些操作。 比如,运行一行代码,指示他们选择All()

我可以用什么最有效的方式将这种行为/事件处理添加到我的所有文本框中


我只是以TextBox为例,因为我计划在今后的WPF库中对其他控件执行类似的操作。

您希望使用附加的行为来完成此操作。下面是我目前用来做这件事的代码,它涵盖了一些奇怪的边缘情况

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>

您希望使用附加的行为来完成此操作。下面是我目前用来做这件事的代码,它涵盖了一些奇怪的边缘情况

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>


使用26个中的@17建议的行为是一种方法。创建自定义TextBox控件并使用此控件而不是内置的TextBox控件是另一个。@mm8实际上,现在您提到我已经将其中一些控件设置为UserControls,每个控件都有自己的位和代码。我真正想要的是避免重复代码。我可以把我想要的代码应用到每个控件后面的代码中,一切都会很好,但正如我所说,我希望尽可能避免这种重复,并将这些通用指令放在一个地方。您不应该将通用代码放在UserControls中,而是放在所有UserControls中使用的自定义TextBox控件类中。使用26中@17建议的行为将是一种方法。创建自定义TextBox控件并使用此控件而不是内置的TextBox控件是另一个。@mm8实际上,现在您提到我已经将其中一些控件设置为UserControls,每个控件都有自己的位和代码。我真正想要的是避免重复代码。我可以把我想要的代码应用到每个控件后面的代码中,一切都会很好,但就像我说的,我希望尽可能避免这种重复,并将这些通用指令放在一个地方。你不应该将通用代码放在UserControls中,而是放在所有UserControls中使用的自定义TextBox控件类中。非常好,我现在开始越来越多地使用行为,它们非常有用。非常好,我现在开始越来越多地使用行为,它们非常有用。