2 回答

TA贡献2037条经验 获得超6个赞
当ComboBox.IsEditable设置为 时True,ComboBox内部将焦点(和键盘焦点)设置为编辑TextBox以使其立即可用于文本输入。这是完全有道理的,因为单击编辑的目的TextBox始终是输入或编辑一些文本。否则,用户必须单击TextBox两次才能使其获得文本输入的焦点(键盘焦点)。
所以,为了防止焦点被窃取,作者将事件标记MouseDown为已处理,即RoutedEventArgs.Handled设置为true。(这就是为什么大多数非预览事件被大多数控件标记为已处理的原因)。
TextBox此外,作者希望在第一次单击编辑时防止插入符号移动(以使其获得焦点):如果编辑没有键盘焦点并且下拉面板是,则PreviewMouseDown事件的RoutedEventArgs.Handled将仅设置为关闭。(这就是为什么第二次点击将通过添加的事件处理程序处理)。trueTextBoxTextBox
要实现您期望的行为,您必须处理上的UIElement.PreviewGotKeyboardFocus事件或附加事件。Keyboard.PreviewGotKeyboardFocusComboBox
或者使用方法注册事件处理程序UIElement.AddHandler并将handledEventsToo参数设置为true:
this.MyComboBox.AddHandler(
UIElement.PreviewMouseDownEvent,
new RoutedEventHandler(MyComboBox_PreviewMouseDown),
true);

TA贡献1796条经验 获得超10个赞
我自己也遇到了同样的问题。一个简单而有效的解决方法是将你的包裹ComboBox在一个轻量级的中ContentPresenter,然后将你的PreviewMouseDown处理程序附加到它,如下所示:
<ContentPresenter x:Name="MyComboBoxWrapper"
PreviewMouseDown="MyComboBoxWrapper_PreviewMouseDown">
<ContentPresenter.Content>
<ComboBox x:Name="MyComboBox" />
</ContentPresenter.Content>
</ContentPresenter>
此外,由于此控件PreviewMouseDown先于事件获取事件ComboBox,因此您不仅可以使用它在甚至看到事件之前预处理事件,还可以通过将事件 arg 的属性设置为“true”来完全ComboBox切断事件。ComboBoxhandled
奇迹般有效!不需要子类化或其他技巧,它只需要树中的轻量级控件!
笔记
正如某些人可能已经考虑的那样,从技术上讲,您可以将PreviewMouseDown事件附加到您的 的任何ComboBox祖先,但您可能必须在该处理程序中包含逻辑以确定您是否实际单击了ComboBoxvs 其他内容。
通过使用显式ContentPresenter(一个难以置信的轻量级元素,它本身没有任何呈现逻辑。它只是托管其他元素),您现在拥有一个专门用于PreviewMouseDown此控件的处理程序。另外,如果您需要四处移动它,它会更便于携带,因为这两个物品可以一起移动。
- 2 回答
- 0 关注
- 264 浏览
添加回答
举报