当另一个元素失去焦点时,需要知道哪个元素会聚焦

时间:2013-07-23 12:51:07

标签: c# wpf windows-runtime wpf-controls winrt-xaml

我在窗口中有很多控件。要求是知道哪个控件从控件的丢失焦点事件中获得焦点。

说,一个文本框,它有焦点。现在我点击一个按钮。在这样做时,需要知道我正在将焦点从文本框丢失焦点事件移动到按钮。

所以我怎么能实现这个......

4 个答案:

答案 0 :(得分:2)

这就是我所做的,也是为我工作的

 protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
   {
     lostFocusControl = e.OldFocus;
   }

   private void PauseBttn_PreviewKeyDown(object sender, KeyEventArgs e)
   {
      /**invoke OnPreviewLostKeyboardFocus handller**/
   }

希望它会有所帮助

答案 1 :(得分:1)

您可以使用FocusManager来处理这个问题, 在LostFocusEvent中,使用FocusManager.GetFocusedElement()

uiElement.LostFocus+=(o,e)=>
{
      var foo=FocusManager.GetFocusedElement();
}

答案 2 :(得分:0)

您是否尝试将控件注册到Control.LostFocus事件,在那里您可以检查Form.ActiveControl,以确定当前具有焦点的控件

答案 3 :(得分:0)

以下课程观察FocusManager的焦点变化,它是一个循环线程,因此您必须忍受它正在运行的事实,但是当焦点发生变化时,它只会引发一个事件,让您知道发生了什么变化。

只需将这两个类添加到项目中即可。

    public class FocusNotifierEventArgs : EventArgs
    {
        public object OldObject { get; set; }
        public object NewObject { get; set; }
    }

    public class FocusNotifier : IDisposable
    {
        public event EventHandler<FocusNotifierEventArgs> OnFocusChanged;
        bool isDisposed;
        Thread focusWatcher;
        Dispatcher dispatcher;
        DependencyObject inputScope;
        int tickInterval;

        public FocusNotifier(DependencyObject inputScope, int tickInterval = 10)
        {
            this.dispatcher = inputScope.Dispatcher;
            this.inputScope = inputScope;
            this.tickInterval = tickInterval;
            focusWatcher = new Thread(new ThreadStart(FocusWatcherLoop))
            {
                Priority = ThreadPriority.BelowNormal,
                Name = "FocusWatcher"
            };
            focusWatcher.Start();
        }

        IInputElement getCurrentFocus()
        {
            IInputElement results = null;
            Monitor.Enter(focusWatcher);
            dispatcher.BeginInvoke(new Action(() =>
                {
                    Monitor.Enter(focusWatcher);
                    results = FocusManager.GetFocusedElement(inputScope);
                    Monitor.Pulse(focusWatcher);
                    Monitor.Exit(focusWatcher);
                }));
            Monitor.Wait(focusWatcher);
            Monitor.Exit(focusWatcher);
            return results;
        }

        void FocusWatcherLoop()
        {
            object oldObject = null;
            while (!isDisposed)
            {
                var currentFocus = getCurrentFocus();
                if (currentFocus != null)
                {
                     if (OnFocusChanged != null)
                        dispatcher.BeginInvoke(OnFocusChanged, new object[]{ this,  new FocusNotifierEventArgs()
                        {
                            OldObject = oldObject,
                            NewObject = currentFocus
                        }});
                    oldObject = currentFocus;
                    }
                }
                Thread.Sleep(tickInterval);
            }
        }

        public void Dispose()
        {
            if (!isDisposed)
            {
                isDisposed = true;
            }
        }
    }

然后在你的代码中,创建一个Focus Notifier类的新实例并挂钩它的OnFocusChanged事件,记得将它放在最后,否则线程会让你的应用程序保持打开状态。

public partial class MainWindow : Window
{
    FocusNotifier focusNotifier;

    public MainWindow()
    {
        InitializeComponent();
        focusNotifier = new FocusNotifier(this);
        focusNotifier.OnFocusChanged += focusNotifier_OnFocusChanged;
    }

    void focusNotifier_OnFocusChanged(object sender, FocusNotifierEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine(e.OldObject);
        System.Diagnostics.Debug.WriteLine(e.NewObject);

    }

    protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
    {
        focusNotifier.Dispose();
        base.OnClosing(e);
    }
}