wpf 避免在鼠标单击时选择可编辑组合框中的所有文本

sqougxex  于 2023-03-24  发布在  其他
关注(0)|答案(1)|浏览(141)

单击TextBox时,光标将放置在我单击的位置。
当单击可编辑的ComboBox时,整个文本被选中,我必须再次单击(几毫秒后)以放置光标。
如何使ComboBox的React与TextBox相同?

<StackPanel>
    <TextBox  Margin="10"
              Text="This is a test" />
    <ComboBox Name="combobox1" Margin="10"
              IsEditable="True"
              Text="This is a test"
               />
</StackPanel>
oyt4ldly

oyt4ldly1#

调用TextBox.SellectAll()ComboBox中的预期实现:

private static void OnPreviewMouseButtonDown(object sender, MouseButtonEventArgs e)
{
    ComboBox comboBox = (ComboBox)sender;

    if (comboBox.IsEditable)
    {
        Visual originalSource = e.OriginalSource as Visual;
        Visual textBox = comboBox.EditableTextBoxSite;

        if (originalSource != null && textBox != null
            && textBox.IsAncestorOf(originalSource))
        {
            if (comboBox.IsDropDownOpen && !comboBox.StaysOpenOnEdit)
            {
                // When combobox is not editable, clicks anywhere outside
                // the combobox will close it.  When the combobox is editable
                // then clicking the text box should close the combobox as well.
                comboBox.Close();
            }
            else if (!comboBox.IsContextMenuOpen && !comboBox.IsKeyboardFocusWithin)
            {
                // If textBox is clicked, claim focus
                comboBox.Focus();
                e.Handled = true;   // Handle so that textbox won't try to update cursor position
            }
        }
    }
}
private static void OnGotFocus(object sender, RoutedEventArgs e)
{
    // When ComboBox gets logical focus, select the text inside us.
    ComboBox comboBox = (ComboBox)sender;

    // If we're an editable combobox, forward focus to the TextBox element
    if (!e.Handled)
    {
        if (comboBox.IsEditable && comboBox.EditableTextBoxSite != null)
        {
            if (e.OriginalSource == comboBox)
            {
                comboBox.EditableTextBoxSite.Focus();
                e.Handled = true;
            }
            else if (e.OriginalSource == comboBox.EditableTextBoxSite)
            {
                comboBox.EditableTextBoxSite.SelectAll();
            }
        }
    }
}

这样的方式MouseDown事件被停止,ComboBox.GotFocus-〉TextBox.GotFocus在鼠标点击时被启动。
为了达到TextBox的行为,你需要订阅TextBox.GotFocus,你可以在ComboBox.Loaded的事件处理程序中完成,然后将TextBox.CaretIndex设置到正确的位置。
所有这些你都可以打包成一个行为:

public class NoSelectAllOnMouseClick : Behavior<ComboBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Loaded += AssociatedObject_Loaded;
    }

    private void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        var tbx = FindVisualChild<TextBox>(AssociatedObject);
        if (tbx != null)
        {
            tbx.GotFocus += Tbx_GotFocus;
        }
    }
    private async void Tbx_GotFocus(object sender, RoutedEventArgs e)
    {
        var tbx = sender as TextBox;
        if (tbx == null)
        {
            return;
        }
        var mousePos = Mouse.GetPosition(tbx);

        if (tbx.InputHitTest(mousePos) != null) //Check point is in the TextBox
        {
            await tbx.Dispatcher.InvokeAsync(() =>
            {
                tbx.CaretIndex = tbx.GetCharacterIndexFromPoint(mousePos, true) + 1;
            });
        }
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Loaded -= AssociatedObject_Loaded;
        base.OnDetaching();
    }

    private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
            if (child != null && child is childItem)
            {
                return (childItem)child;
            }
            else
            {
                childItem childOfChild = FindVisualChild<childItem>(child);
                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }
        }
        return null;
    }
}

并使用它:

<ComboBox x:Name="combobox1" Margin="10" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    IsEditable="True"
    Text="This is a test">
    <i:Interaction.Behaviors>
        <beh:NoSelectAllOnMouseClick/>
    </i:Interaction.Behaviors>
</ComboBox>

相关问题