PropertyGrid slows down the UI

Grids for WPF Forum

Posted 9 years ago by Craig - Varigence, Inc.
Version: 10.2.0532
Platform: .NET 4.0
Environment: Windows 7 (32-bit)
Avatar
A common UI pattern in our applications is to have a selected item be displayed in the property grid. We've been noticing that when we add items in our UI (which are immediately selected), the add takes longer than normal. Additionally, when scrolling through ListBoxes and TreeViews, scrolling is sluggish and takes considerably longer. After doing some debugging, we discovered the issue was the property grid binding. When we removed the binding, our UI got noticeably snappier.

I'm sending along a sample application that demonstrates the scrolling issue. We have two listboxes that are bound to collections of 5,000 objects. For a ListBox that's not bound to the property grid, scrolling the 5,000 items takes 2:45. For a ListBox whose SelectedItem is bound to the property grid, it took nearly 5 minutes to scroll only 2,000 items.

If you have any suggestions on how this can be improved on our side, that'd be great. However, considering how vanilla the sample is, it seems like this is really a property grid issue where it needs better performance so it doesn't slow down other UI operations.

Please don't hesitate to contact me with any questions.

Thanks,

-Craig

Comments (7)

Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Craig,

When you scroll through the ListBox quickly, the PropertyGrid must updated for every selection change. This is definitely going to add some overhead. You can tell the PropertyGrid to skip updating until the user stops scrolling. This keeps the scrolling fast and the PropertyGrid will update once the user stops. The following type of code will accomplish this (which could probably be wrapped in an attached behavior):
private bool isUpdating = false;
private void propGridListBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) {
    if (!this.isUpdating && (e.Key == Key.Up || e.Key == Key.Down || e.Key == Key.PageUp || e.Key == Key.PageDown)) {
        this.isUpdating = true;
        this.propgrid.BeginUpdate();
    }
}

private void propGridListBox_PreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e) {
    if (this.isUpdating && (e.Key == Key.Up || e.Key == Key.Down || e.Key == Key.PageUp || e.Key == Key.PageDown)) {
        this.isUpdating = false;
        this.propgrid.EndUpdate();
    }
}


Actipro Software Support

Posted 9 years ago by Craig - Varigence, Inc.
Avatar
First off, I appreciate your feedback on this. Unfortunately, while your suggested approach could resolve scrolling issues via key presses, there are other property grid slow downs it won't address. For instance, consider a datagrid where each time a new object is added to its bound collection, the item appears as a new row and is selected. Additionally, the datagrid's SelectedItem is bound to the property grid. We basically have this setup in our application and have seen that when rapidly adding new items, there's a noticeable slowdown that disappears when the property grid isn't bound to the control's SelectedItem. Thus, we'd like to find a solution that addresses the property grid slowdown in a general manner, not just for scrolling.

To handle this in a more centralized way, would it be possible to implement something like the following:
1. Have a DP (let's call it "LatestSelectedObject") that stores the latest item assigned to it.
2. When the property grid indicates that it has finished an update, perhaps via an event (might SelectedObjectsChanged work?), if LatestSelectedObject is not null, then we update the property grid's SelectedObject binding with the LatestSelectedObject value and clear LatestSelectedObject.

Do you think this mechanism could work? Are there any potential issues I'm not seeing? It's clearly similar to your suggested approach for scrolling, except that I can't use EndUpdate as I'd never know when to call it.

Also, generally speaking, can we expect better property grid performance in later releases? Is property grid performance a problem that you're still working on?

Thanks again,

-Craig
Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Craig,

Your approach would probably work, but there is one main issue. The PropertyGrid extends the native WPF TreeView, which is very hard to determine if things are "loaded". Each node in the tree is responsible for loading it's children, if it needs to load them at all (i.e. IsExpanded == false). There is no centralized event to say that everything has been loaded. You may be able to use the LayoutUpdated event on the PropertyGrid, but that may not fire when appropriately.

You could probably implement something that simply ensures the PropertyGrid.SelectedObject is only updated once a second or two. So in a change handler for the LatestSelectedObject, you'd check the last time you updated PropertyGrid.SelectedObject. If it's been more than X seconds, you'd update PropertyGrid.SelectedObject immediately. If it's been less than X seconds, you'd start a timer to update PropertyGrid.SelectedObject.

Finally, one suggestion to improve performance we've received from other customers is to use a proxy object. Basically, the proxy object wraps the object that should be presented, and reexposes the same properties (whose getters and setters simply call into the wrapped object). Then instead of setting PropertyGrid.SelectedObject, you'd update the proxy object to point to the new object. This effectively keeps the same visuals in the PropertyGrid, and simply updates the binding values.

The problems with this approach are that it only works if the objects are of the same type and expose the same properties. In addition, any custom filters or sorting will not be automatically applied when the object wrapped by the proxy is updated.

We have a TODO item to research this idea further. To possibly make a generic proxy object, which overcomes some or all of the limitations above. I've added this forum post to that TODO item, so you would be notified when it's completed.


Actipro Software Support

Posted 9 years ago by Craig - Varigence, Inc.
Avatar
Now that we have some ideas for handling scenarios where we select consecutive items of the same type, what about situations where the user selects heterogeneous items? For example, they might be using a XAML designer and selecting different controls, expecting each control to appear in the property grid as they're selected.

Although it sounds like there isn't a quick fix, is there anything we can do to help give item load/display a boost? Perhaps disable or avoid certain features that may strongly affect performance? Alter the editor control templates? Override certain property grid functions to throw away logic we don't use? Even in the homogeneous case, while filtering SelectedObject firings will certainly help, each selection may still cause a noticeable hit on the UI thread.

Also, are you aware of any examples of the proxy object approach that I could look at?

Thanks again,

-Craig
Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Craig,

The best way to increase performance is to use virtualization. For more information on that, please see the "Optional Optimizations" topic in our help file. Aside from the settings described in that help topic, the only way to increase the load time is to reduce the number of properties displayed. This can be done through the use of a DataFilter or using properties like AreInheritedPropertiesBrowsable. If you use categories, then you can also set PropertyGrid.AreCategoriesAutoExpanded to false. Usually though, enabling virtualization is your best bet.

We don't currently have any examples showing a proxy object, generic or otherwise. But, the generic one would need to implement ICustomTypeDescriptor, while a specific one would simply expose the exact same properties as the type it is wrapping.


Actipro Software Support

Posted 7 years ago by Craig - Varigence, Inc.
Avatar

I'm just curious if there have been any major changes to the PropertyGrid to further decrease load times since the last time we discussed this topic. 

Looking over the thread, and from what I recall, I know there was discussion of a proxy object but I don't see any samples. Was there ever an opportunity to research that idea further?

Thanks,

-Craig

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

Hi Craig,

There may have been some minor tweaks but the "Optional Optimizations” topic in the documentation has anything that we recommend for performance improvement.

We haven't really done anything new with the proxy object idea.  If I remember correctly, that only worked if you were always using PropertyGrid on the same Type of object.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 12 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.