【问题标题】:WPF ComboBox PreviewMouseDownWPF ComboBox PreviewMouseDown
【发布时间】:2019-06-27 18:26:48
【问题描述】:

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

<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 不起作用?

【问题讨论】:

  • 好吧,它不能按照你想要的方式工作。他们为什么这样设计并不重要。你在那个活动中做什么? GotFocus 活动会是更好的选择吗?如果用户点击组合框而不是点击它会怎样?
  • 我有一个带有组合框的弹出窗口。还有一个 WebBrowser 控件来显示 pdf 文档。我面临的问题是,当 pdf 具有键盘焦点并且我单击组合框以编辑文本时,文本被选中,但所有键盘操作仍然发送到 WebBroser 中的 pdf。

标签: c# .net wpf combobox


【解决方案1】:

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

此外,作者希望在第一次单击编辑TextBox 时阻止插入符号的移动(以使其获得焦点):PreviewMouseDown 事件的RoutedEventArgs.Handled 设置为true,如果编辑TextBox 没有键盘焦点并且下拉面板关闭。 (这就是为什么对TextBox 的第二次点击将通过添加的事件处理程序进行处理。

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

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

this.MyComboBox.AddHandler(
  UIElement.PreviewMouseDownEvent, 
  new RoutedEventHandler(MyComboBox_PreviewMouseDown), 
  true);

【讨论】:

【解决方案2】:

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

<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任何 祖先,但您可能必须在该处理程序中包含逻辑以确定您是否'重新实际点击 ComboBox 与其他内容。

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

【讨论】:

  • 我也使用了 ContentPresenter 技巧。非常简单的解决方案,比其他方法更容易理解/可读。
猜你喜欢
  • 2017-06-06
  • 2011-01-10
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-01
  • 2013-06-30
相关资源
最近更新 更多