tags:

views:

131

answers:

3

I've built several user controls in WPF and they all get added to a canvas. I want to add a behaviour that keep tracks of the currently selected usercontrol. A usercontrol should be selected when:

  1. The mouse clicks on it;
  2. when it recieve focus;
  3. when either of the two above happens to a subcontrol of the usercontrol.

Is there any way to handle this purely by using the focus mechanism of WPF or will I need to take care of this myself with assistance of the focus classes?

I've read up upon the new way of handling focus in WPF, and the problem I'm facing is that the keyboard focus determines what the currently selected object is, but some parts of the my control can't recieve keyboard focus so even though these parts are clicked, the usercontrol doesn't recieve focus.

I'm looking for advice on how to implement this feature and how much I could/should rely on the focus mecanisms. Ultimatively I wouldn't mind if only a single object could be selected, but if it's easily extendable to multi-select then I wouldn't mind this either.

Just to clarify, I know I could build this manually by handling a lot of events and keeping track of states, but I was just hoping an easier approach was available.

A: 

You could use the UIElement.IsKeyboardFocusWithin property, which is true when the UIElement or one of its children has keyboard focus. It is a dependency property, so you can easily use it for a trigger in a style

Thomas Levesque
The problem is that the usercontrol has parts of it that cannot recieve keyboard input, and when these are clicked the control should still be selected.
Qua
A: 

You can set the logical focus to the control when any of the child gets the keyboard focus using FocusManager.IsFocusScope="True". Setting the keyboard focus to the control or trying to do will eat the keys for the child controls.

You can use UIElement.IsKeyboardFocusWithin to set the focus of the control if any of the children has focus.

You can read this article which I think describes the difference between Logical and Keyboard focus quite well:

http://www.pluralsight.com/community/blogs/eburke/archive/2009/03/18/why-is-focus-in-wpf-so-tricky-managing-and-understanding-focus-in-a-wpf-application.aspx

Yogesh
A: 

Combine UIElement.IsKeyboardFocusWithin with a PreviewMouseDown handler:

  1. When PreviewMouseDown is called, set a flag and schedule callback using Dispatcher.BeginInvoke at DispatcherPriority.Input to set focus to the UserControl if the flag is still set.

  2. Set a handler for UIElement.IsKeyboardFocusWithin property changes in your UserControl. When the handler fires, clear the flag.

The idea here is that if you click anywhere on the UserControl and keyboard focus does not result in the focus being moved into the UserControl, force it into the UserControl.

FYI, here's roughtly what step 1 looks like in code:

public override OnPreviewMouseDown(MouseButtonEventArgs e)
{
  _mouseClickedButNoFocus = true;
  Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
  {
    if(_mouseClickedButNoFocus)
      Focus();
  });
}
Ray Burns