【问题标题】:C# ComboBox GotFocusC# ComboBox GotFocus
【发布时间】:2009-10-12 13:36:28
【问题描述】:

我有一个使用 WPF 的 C#ComboBox。我有在ComboBoxGotFocus 被激活时执行的代码。问题是每次从ComboBox 中进行选择时都会执行GotFocus 事件。例如,GotFocus 在您第一次单击 ComboBox 时执行,然后在您进行选择时执行,即使您没有单击任何其他控件。

如果在列表中进行了选择,或者事件处理程序中是否有标志或其他东西可用于确定GotFocus 事件处理程序是否作为用户选择列表中的项目的结果?

【问题讨论】:

标签: c# wpf combobox focus


【解决方案1】:

你可以通过下次验证来解决这个问题:

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;
    }
}

从这些示例中选择您的应用程序真正需要的更多内容。

【讨论】:

  • 非常感谢您的精彩解释!
  • 此解决方案似乎不适用于可编辑的组合框。看起来OriginalSource 在这种情况下是TextBox 而不是ComboBoxItem。我已经尝试了上述代码的不同变体来解决这个变化,但还没有成功。如果您能调查一下,将不胜感激。
【解决方案2】:

我对 WPF 不太感兴趣;但是如果您尝试检测列表的更改(单击新值等),您可以使用 SelectedIndexChanged 事件..

另一方面,如果您真的只想知道控件何时获得焦点,您可以通过说类似的话来过滤它;

if (combo1.Focused && combo1.SelectedIndex == -1)
{
     ...
}

..?这实际上取决于您要检测的内容。

【讨论】:

    【解决方案3】:

    另一种解决方法是判断新的焦点元素是否是组合框中的现有项。如果为 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... */
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-06
      • 1970-01-01
      • 1970-01-01
      • 2016-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多