WPF:无法控制键盘焦点

时间:2013-10-08 13:02:00

标签: c# wpf wpf-controls focus .net-4.5

本周我遇到的问题一直困扰着我。总结一下,问题是当我左键单击另一个控件时,我无法从代码中将键盘焦点放到ComboBox上。

具体来说,我有一个CustomControll,其中包含一个Scrollview,其中包含另一个CustomControll,另一个带有ComboBox的CustomControll作为子项。我会说清楚这一点:

  • 滚动型
    • DayView(CustomControl)
      • 滚动型
        • 一些不相关的控件
          • TimelineEvent(CustomControl)
    • EventEditor(CustomControl)
      • 组合框

我想要做的是当用户左键单击或以其他方式选择TimelineEvent(例如创建它)时,通过调用Keyboard.Focus(myComboBox)来为ComboBox提供键盘焦点。发生的事情是我的第一次LMB点击,TimelineEvent获得键盘焦点。通过第二次单击,DayView的父级获得焦点(它是滚动视图)

我无法解释这种行为。我在代码中创建了断点并确保它被执行。我还将OnLostKeyboardFocus,OnGotKeyboardFocus及其预览的监听器添加到TImelineEvent,包含它的ScollView和组合框。我已经把它打印到控制台了,这就是我得到的:

[First LMB down on TimelineEvent]
System.Windows.Controls.ScrollViewer got focus
[LMB up]
EDP.EDPTid.CustomControlLibrary.TimelineColumn.TimelineEvent lost focus
EDP.EDPTid.CustomControlLibrary.TimelineColumn.TimelineEvent got focus
The thread '<No Name>' (0x19bc) has exited with code 0 (0x0).
[Second LMB down on the same element]
System.Windows.Controls.ScrollViewer lost focus
System.Windows.Controls.ScrollViewer got focus
[LMB Up]
EDP.EDPTid.CustomControlLibrary.TimelineColumn.TimelineEvent lost focus
EDP.EDPTid.CustomControlLibrary.TimelineColumn.TimelineEvent got focus
System.Windows.Controls.ComboBox Items.Count:29 lost focus
System.Windows.Controls.ComboBox Items.Count:29 got focus

在最后两行,您可以看到ComboBox似乎得到了键盘焦点,但是当我按下键时,很明显它是最顶端的滚动视图获得键盘焦点,我也使用Snoop确认了它。 / p>

以下是在TimelineEvent.MouseLeftButtonUp上执行的代码:

public class DayView
{
...
    public void SelectEvent(TimelineEvent sender, bool useSpecialFocus)
    {
        EventEditor.EditedEvent = null;
        HideControl(EventEditor);

        foreach (TimelineEvent evnt in Timeline.EventContainer.GetEvents())
        {
            if (sender != null && evnt.Data.Id == sender.Data.Id)
            {
                EventEditor.EditedEvent = sender;
                ShowControl(EventEditor);

                evnt.MarkAsSelected(true);
                if (evnt.IsMouseOver)
                {
                    evnt.ShowButtons();
                }
                Expand();

                Keyboard.Focus(EventEditor.EventType);
            }
            else
            {
                evnt.MarkAsSelected(false);
                evnt.HideButtons();
            }
        }
    }

    private void HideControl(FrameworkElement control)
    {
        animator.AnimateOpacity(control.Opacity, 0.0d, new TimeSpan(0, 0, 0, 0, 100), false, control, Visibility.Hidden);
    }

    private void ShowControl(FrameworkElement control)
    {
        animator.AnimateOpacity(control.Opacity, 1.0d, new TimeSpan(0, 0, 0, 0, 100), false, control,Visibility.Visible);
        control.Visibility = Visibility.Visible;
    }
}

public class TimelineEvent
{
    ...
    public void MarkAsSelected(bool selected, bool useSpecialFocus)
    {
        if (SelectedBorder != null)
        {
            SelectedBorder.BorderThickness = new Thickness(selected ? 2 : 0);
            IsSelected = selected;

            Focus();                        
        }
    }
}

您可能会注意到的一件事是我首先调用TimelineEvent.Focus()然后调用Keyboard.Focus(EventEditor.EventType)。我认为这可能是我的问题的原因,所以我评论了Focus的调用,它是遗留代码而不是真正需要的。应用程序开始表现得非常不稳定 - 大多数仍在SelectEvent函数中执行的代码停止工作! EventEditor没有显示,TimelineEvent没有获得2号边框,并且焦点被放在源自ExternalCode的时间轴事件的Scrollview父级,因此我无法跟随该调用。

我已经坚持了两天这个问题而没有获得任何见解,任何帮助都会受到极大的关注。

0 个答案:

没有答案