关于c#:WPF ComboBox PreviewMouseDown

WPF ComboBox PreviewMouseDown

我有一个可编辑的组合框和一个文本框。

1
2
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="86,149,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
<ComboBox x:Name="comboBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="282,150,0,0" IsEditable="True" PreviewMouseDown="ComboBox_PreviewMouseDown"/>

当焦点位于文本框上并单击组合框时,我不明白为什么ComboBox_PreviewMouseDown不触发。它只是突出显示组合框中的文本并设置焦点。单击组合框已具有焦点时,将触发PreviewMouseDown

这是在发生什么事吗?为什么不集中的组合框中的PreviewMouseDown无法正常工作?


ComboBox.IsEditable设置为True时,ComboBox在内部将焦点(和键盘焦点)设置为编辑TextBox,使其立即可用于文本输入。完全有道理,因为单击编辑TextBox时总是要输入或编辑某些文本。否则,用户将不得不单击TextBox两次,以使其获得文本输入的焦点(键盘焦点)。
因此,为防止窃取焦点,作者将MouseDown事件标记为已处理,即RoutedEventArgs.Handled设置为True。 (这就是为什么大多数非预览事件被大多数控件标记为已处理的原因。)

此外,作者想防止第一次单击插入编辑TextBox时插入符号的移动(以使其成为焦点):PreviewMouseDown事件的RoutedEventArgs.Handled仅设置为True ,如果edit TextBox没有键盘焦点并且下拉面板关闭。 (这就是第二次点击TextBox的原因,将由添加的事件处理程序处理)。

要实现预期的行为,必须处理UIElement.PreviewGotKeyboardFocus事件或ComboBox上附加的Keyboard.PreviewGotKeyboardFocus事件。

或者使用UIElement.AddHandler方法注册事件处理程序,并将handledEventsToo参数设置为True

1
2
3
4
this.MyComboBox.AddHandler(
  UIElement.PreviewMouseDownEvent,
  new RoutedEventHandler(MyComboBox_PreviewMouseDown),
  true);


我自己也遇到了同样的问题。一个简单有效的解决方法是将ComboBoxpackage在轻量级的ContentPresenter中,然后将PreviewMouseDown处理程序附加到该处理程序,如下所示:

1
2
3
4
5
6
7
8
<ContentPresenter x:Name="MyComboBoxWrapper"
    PreviewMouseDown="MyComboBoxWrapper_PreviewMouseDown">

    <ContentPresenter.Content>
        <ComboBox x:Name="MyComboBox" />
    </ContentPresenter.Content>

</ContentPresenter>

此外,由于此控件在ComboBox之前先获得PreviewMouseDown事件,因此,您不仅可以使用它在ComboBox看到事件之前对其进行预处理,还可以切断ComboBox完全通过将事件arg的handled属性设置为'true。'

像魅力一样工作!无需子类化或其他技巧,它只需要树中的轻量级控件即可!

笔记

正如某些人所考虑的那样,从技术上讲,您可以将PreviewMouseDown事件附加到ComboBox的任何祖先,但随后可能必须在该处理程序中包含逻辑,以确定您是否实际上单击了与其他内容。

通过使用显式的ContentPresenter(一种本身没有任何渲染逻辑的轻量级元素,它仅承载其他元素),您现在拥有了专门用于此控件的PreviewMouseDown处理程序。另外,由于这两个物品可以一起旅行,因此它在您需要移动时更加轻便。