Listening for Keyboard Focus on PropertyGrid Items

Grids for WPF Forum

Posted 4 years ago by Chris Carter
Version: 15.1.0621
Avatar

What's the best way to detect keyboard focus on a PropertyGrid item?

I've found TextBoxValueTemplateKey and DefaultValueTemplateKey, but I don't know whether I should really be replacing the existing template when I only need to listen for an event.

My specific scenario may help: I need to intercept keyboard input for my custom onscreen keyboard (not my decision). This is working for normal TextBoxes, but PropertyGridPropertyItems are giving me trouble.

I'm using attached properties, and they're getting me into this if statement, but none of my handlers ever get activated... (The first three sometimes miss the very first action on TextBoxes, although not in my very simple test application.)

var propGridItem = element as PropertyGridPropertyItem;

if (propGridItem != null)
{
	propGridItem.AddHandler(FrameworkElement.MouseDownEvent, new MouseButtonEventHandler(FrameworkElement_MouseDown), true);
	propGridItem.AddHandler(FrameworkElement.TouchDownEvent, new RoutedEventHandler(UIElement_Selected), true);
	propGridItem.AddHandler(FrameworkElement.StylusDownEvent, new RoutedEventHandler(UIElement_Selected), true);
	propGridItem.AddHandler(UIElement.GotFocusEvent, new RoutedEventHandler(UIElement_Selected), true);
}

That is, I never see program control in here:

private static void FrameworkElement_MouseDown(object sender, MouseButtonEventArgs e)
{
	UIElement_Selected_impl(sender as UIElement);
}

private static void UIElement_Selected(object sender, RoutedEventArgs e)
{
	UIElement_Selected_impl(sender as UIElement);
}

How should I be doing this?

[Modified 4 years ago]

Comments (12)

Posted 4 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Chris,

The PropertyGridPropertyItem isn't what actually gets focus, but rather the controls within the editor template it's using that do.  So there might be a nested TextBox within it or other controls, depending on which editor template gets pulled for the current property.  Could you watch the item's IsKeyboardFocusWithin property instead?


Actipro Software Support

Posted 4 years ago by Chris Carter
Avatar

Looking at that property, I thought IsKeyboardFocusWithinChanged would do it: https://msdn.microsoft.com/en-us/library/system.windows.uielement.iskeyboardfocuswithinchanged(v=vs.110).aspx But it's not firing either. I'm reluctant to try a constantly running timer to poll for "true" on 50-odd items...

I have two onscreen keyboards, one for numeric input and one for alphanumeric, so I can't style all items to use one or the other. I was hoping for something more elegant, but I guess I need to do something similar to this: http://stackoverflow.com/questions/10279092/how-to-get-children-of-a-wpf-container-by-type

[Modified 4 years ago]

Posted 4 years ago by Chris Carter
Avatar

The visual and logical trees don't have anything in them, under the property grid item. As I understand the answer to this question, the logical tree is populated in usercode. Does this mean someone at Actipro decided against populating it for some reason? Maybe that's a feature which could be added?

Meanwhile, I still don't know how I can get hold of that textbox...

Answer - Posted 4 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

HI Chris,

The PropertyGridDataAccessorItem class is actually the one that is within the UI.  It is the UI container created each item in the PropertyGrid, due to this PropertyGrid method:

protected override DependencyObject GetContainerForItemOverride() {
	return new PropertyGridDataAccessorItem();
}

The PropertyGridDataAccessorItem class also has this method since each tree node can generate child containers.  What you possibly could do is make a class that inherits PropertyGridDataAccessorItem and in that, watch IsKeyboardFocusWithinChanged.  Note you'd need to override both the PropertyGrid and PropertyGridDataAccessorItem versions of GetContainerForItemOverride to return your new custom class.


Actipro Software Support

Posted 4 years ago by Chris Carter
Avatar

This tool is showing me what I think is the visual tree, by means I have not yet divined from its source. I notice that the textbox has a name of "textBox," which might be helpful if I had a reference to the most-nested PropertyGridDataAccessorItem. I climbed the logical tree to the containing PropertyGrid (which I see in Snoop), but couldn't find a way down the visual tree from there. This seems to be just because the window is not yet rendered, and I suspect I can solve that with the ContentRendered event... tomorrow.

From past experience, overriding a XAML element class is a painful process that I would rather avoid. Traversing the visual tree isn't necessarily any better, though.

Posted 4 years ago by Chris Carter
Avatar

Using the visual tree requires that I match "data accessors" with logical items, which seems really brittle. So I attempted to override the classes as suggested, but all of the PropertyGrid-specific dependency properties break:

The member "AreDefaultSortDescriptionsEnabled" is not recognized or is not accessible.
The member "Items" is not recognized or is not accessible.
The member "SummaryHeight" is not recognized or is not accessible.

Is there something I should be doing to enable use of these on my subclass?

Posted 4 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Chris,

If you'd like to make a new simple sample project showing these errors, please reference this thread and send it in a renamed .zip file extension to our support address.  We can use that to debug it to see where the code is going wrong.


Actipro Software Support

Posted 4 years ago by Chris Carter
Avatar

The problem I described disappears in a simple project.

On the bright side, the simple project worked without modification, but that doesn't do the real application any good. Time to sharpen my XAML debugging skills.

Thanks for the help.

[Modified 4 years ago]

Posted 4 years ago by Chris Carter
Avatar

Scratch that, maybe Visual Studio had been open too long; I don't have that problem anymore.

When I generate a data accessor, I don't see any way to associate it with the item it's replacing/containing. I need to use a dependency property on my subclass of PropertyGridPropertyItem to inform my PropertyGridDataAccessorItem which keyboard to open. How can dependency property information propagate to the visual tree node?

Posted 4 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Chris,

You could override the PropertyGrid and PropertyGridDataAccessorItem.PrepareContainerForItemOverride methods.  That is standard WPF ItemsControl stuff where the container (PropertyGridDataAccessorItem) and its wrapped data item (PropertyGridPropertyItem) get passed in.  Then you could configure your property there for each item.


Actipro Software Support

Posted 4 years ago by Chris Carter
Avatar

Alright, thanks for that new search keyword. I think I have enough information to find my way from here.

For being part of basic ItemsControl usage, PrepareContainerForItemOverride isn't mentioned much. The only promising resources I've found are:

http://wpf.2000things.com/tag/preparecontainerforitemoverride/

http://www.silverlightshow.net/items/ItemsControl-from-scratch-to-your-own-controls.aspx (note it's about Silverlight, but close enough)

https://social.msdn.microsoft.com/Forums/en-US/d1fe17de-f994-41c6-82cc-ae14432322b8/itemscontrolpreparecontainerforitemoverride-not-called-for-new-items?forum=wpf (a question that's probably deep enough that an answer will explain all the important stuff)

Anyway, thanks again for the help. Maybe this post will serve as a breadcrumb for someone, or at least help me remember those resources.

Posted 4 years ago by Chris Carter
Avatar

Now that I've properly overridden PropertyGridDataAccessorItem, Selected works much better than IsKeyboardFocusWithinChanged, which fires way too often. (GotFocus has weird issues with window focus that I hadn't seen before.)

When overriding PrepareContainerForItemOverride, make sure to call the base implementation (which I didn't realize was there).

[Modified 4 years ago]

The latest build of this product (v2018.1 build 0675) was released 9 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.