Sankarann
Sankarann

Reputation: 2665

Need know which element get focus when another element lost focus

I have many controls in a window. Requirement is to know which control gets the focus from the lost focus event of a control.

Say, A Text box and it has the focus. Now I am clicking a button. while doing this, need to know that i am moving the focus to button from the Text box lost focus event.

So how could i achieve this..

Upvotes: 2

Views: 4188

Answers (4)

Andy
Andy

Reputation: 6466

The following class watches the FocusManager for changes in focus, it's a looped thread so you have to put up with the fact that it's running but when focus changes it will just raise an event letting you know what changed.

Just add these two classes to your project.

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

Then in your code behind, create a new instance of the Focus Notifier class and hook on to it's OnFocusChanged event, remember to dispose it at the end or the thread will keep your app open.

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

Upvotes: 0

Arun Selva Kumar
Arun Selva Kumar

Reputation: 2732

You can use FocusManager to handle this, In your LostFocusEvent, Use FocusManager.GetFocusedElement()

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

Upvotes: 1

Rajeev Bera
Rajeev Bera

Reputation: 2019

This is what I did and its working for me

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

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

Hope it will help

Upvotes: 3

Visions
Visions

Reputation: 947

have you tried to register your controls to Control.LostFocus event and there you can check for Form.ActiveControl, to determine which control currently has the focus

Upvotes: 0

Related Questions