我有一个使用WPF的C#ComboBox
。我有代码在ComboBox
的{{1}}被激活时执行。问题是每次从GotFocus
进行选择时都会执行GotFocus
事件。例如,ComboBox
在您第一次点击GotFocus
时执行,然后在您进行选择时执行,即使您没有点击任何其他控件。
如果在列表中进行选择,或者事件处理程序中是否有标志或其他可用于确定是否已触发ComboBox
事件处理程序的事件,是否可以阻止此事件触发用户选择列表中的项目的结果是什么?
答案 0 :(得分:13)
您可以通过下一次验证解决此问题:
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(ComboBoxItem))
return;
//Your code here
}
此代码将过滤项目中的所有焦点事件(因为它们使用气泡路由事件)。但是还有另一个问题 - WPF ComboBox焦点的特定行为:当您打开包含项目的下拉列表时,您的ComboBox将失去焦点并获得项目。当你选择一些项目 - 失去焦点的项目和ComboBox回来。下拉列表就像另一个控件。您可以通过简单的代码看到这一点:
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
Trace.WriteLine("Got " + DateTime.Now);
}
}
private void myComboBox_LostFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
Trace.WriteLine("Lost " + DateTime.Now);
}
}
因此,无论如何你都会得到至少两个焦点事件:当你选择ComboBox时以及当你选择它时(焦点将返回ComboBox)。
要在选择项目后过滤返回的焦点,您可以尝试将DropDownOpened
/ DropDownClosed
个事件与某些字段标记一起使用。
所以最终的代码只有1个获得焦点的事件:
private bool returnedFocus = false;
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem) && !returnedFocus)
{
//Your code.
}
}
private void myComboBox_LostFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
ComboBox cb = (ComboBox)sender;
returnedFocus = cb.IsDropDownOpen;
}
}
从这个示例中选择您的应用程序实际需要的内容。
答案 1 :(得分:0)
我对WPF不太热;但是,如果您尝试检测列表的更改(单击新值等),则可以使用SelectedIndexChanged事件..
另一方面,如果您确实想知道控件何时被聚焦,可以通过说出类似的内容来过滤它吗?
if (combo1.Focused && combo1.SelectedIndex == -1)
{
...
}
..?这实际上取决于你想要检测的内容。
答案 2 :(得分:0)
另一种解决方案是确定新的聚焦元素是否是组合框中的现有项目。如果为true,则不应执行LostFocus事件,因为组合框仍然具有焦点。否则,组合框外的元素会获得焦点。
在下面的代码片段中,我在自定义组合框类中添加了功能
public class MyComboBox : System.Windows.Controls.Combobox
{
protected override void OnLostFocus(RoutedEventArgs e)
{
//Get the new focused element and in case this is not an existing item of the current combobox then perform a lost focus command.
//Otherwise the drop down items have been opened and is still focused on the current combobox
var focusedElement = FocusManager.GetFocusedElement(FocusManager.GetFocusScope(this));
if (!(focusedElement is ComboBoxItem && ItemsControl.ItemsControlFromItemContainer(focusedElement as ComboBoxItem) == this))
{
base.OnLostFocus(e);
/* Your code here... */
}
}
}