Ala*_*ain 5 c# wpf xaml .net-4.0
当用户从组合框中选择值时,如果他们选择了一个值,则会触发"SelectionChanged"事件,并设置新值并且一切正常.但是,如果他们决定不更改值并单击UI上的其他位置(如他们想要编辑的文本框),则必须单击两次 - 第一次单击只需关闭组合框弹出窗口,下一次单击将关注他们想要在第一次点击时激活的元素.
如何防止组合框弹出窗口在第一次点击时劫持焦点目标?
我已经尝试过监视ComboBox_LostFocus事件,但这会在错误的时间触发.当用户单击下拉列表并显示弹出列表时,ComboBox_LostFocus事件将触发 - 它将失去焦点到它自己的下拉列表.我不想做任何改变.当用户点击然后弹出窗口关闭时,ComboBox永远不会重新获得焦点(焦点只是'丢失'到所有东西),因此这个事件是无用的.
我想我可能找到了解决方案.组合框确实有一个DropDownClosed事件 - 问题是它不是RoutedEvent,所以你不能为ComboBox创建一个样式并让它们都通过EventSetter继承事件.(你得到错误'DropDownClosed' must be a RoutedEvent registered with a name that ends with the keyword "Event"
)
但是,Loaded
事件是一个RoutedEvent,所以我们可以在样式中挂钩:
<Style x:Key="ComboBoxCellStyle" TargetType="ComboBox">
<EventSetter Event="Loaded" Handler="ComboBox_Loaded" />
</Style>
Run Code Online (Sandbox Code Playgroud)
现在我们有一个事件总是会在ComboBox完成任何其他事情之前触发,我们可以挂钩到我们真正关心的事件:
private void ComboBox_Loaded(object sender, RoutedEventArgs e)
{
((ComboBox)sender).DropDownClosed -= ComboBox_OnDropDownClosed;
((ComboBox)sender).DropDownClosed += new System.EventHandler(ComboBox_OnDropDownClosed);
}
Run Code Online (Sandbox Code Playgroud)
现在我终于可以访问DropDown关闭时触发的事件,我可以执行我需要的任何操作,以确保焦点在麻烦的ComboBox上终止.在我的情况下,以下内容:
void ComboBox_OnDropDownClosed(object sender, System.EventArgs e)
{
FrameworkElement visualElement = (FrameworkElement)sender;
while( visualElement != null && !(visualElement is DataCell) )
visualElement = (FrameworkElement)visualElement.TemplatedParent;
if( visualElement is DataCell )
{
DataCell dataCell = (DataCell)visualElement;
dataCell.EndEdit();
if( !(dataCell.ParentRow is InsertionRow) ) dataCell.ParentRow.EndEdit();
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个ComboBox作为GridView中DataCell的模板,这个特殊问题阻止了DataRow在用户弹出打开ComboBox然后在网格外部单击时结束编辑.
这是我犯这个bug的最大问题.如果用户单击,则在此事件中设置焦点的次要问题.组合框也可能刚刚关闭,因为用户按Tab键或逃脱,所以我们不能只设置焦点到鼠标位置.我们需要有关导致DropDownClosed事件触发的更多信息.可能意味着在_Loaded事件处理程序中挂钩更多未被路由的事件.
归档时间: |
|
查看次数: |
6592 次 |
最近记录: |