The performance of the property grid isn't great, and it appears that the performance degrades on some scenarios.
We are placing the property grid inside a RadDocking. The pane itself has the IsHidden bound to a property, since the software is an IDE and depending on the type of the active document, we either show a toolbox and / or a property grid.
I can see with dotTrace that something is leaking (The weakevent listener is raising the handler more time than it should).
Code:
MainWindow.xaml:
<
Window
x:Class
=
"RadPropertyGridPerformanceIssue1.MainWindow"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
xmlns:local
=
"clr-namespace:RadPropertyGridPerformanceIssue1"
Title
=
"MainWindow"
Height
=
"350"
Width
=
"525"
x:Name
=
"self"
>
<
Grid
>
<
telerik:RadDocking
>
<
telerik:RadSplitContainer
telerik:DockingPanel.InitialSize
=
"228,650"
Name
=
"RightContainer"
InitialPosition
=
"DockedRight"
Orientation
=
"Vertical"
>
<
telerik:RadPaneGroup
>
<
telerik:RadPane
CanUserClose
=
"False"
x:Name
=
"propertiesPane"
Header
=
"Properties Window"
CanDockInDocumentHost
=
"False"
telerik:RadDocking.SerializationTag
=
"Properties"
DataContext
=
"{Binding ElementName=self, Path=DataContext}"
IsHidden
=
"{Binding ElementName=self, Path=IsHidden, Mode=TwoWay}"
>
<
local:PropertiesControl
DataContext
=
"{Binding}"
/>
</
telerik:RadPane
>
</
telerik:RadPaneGroup
>
</
telerik:RadSplitContainer
>
</
telerik:RadDocking
>
<
StackPanel
HorizontalAlignment
=
"Left"
>
<
Button
Click
=
"Button_Click"
>Toggle Visibility</
Button
>
<
Button
Click
=
"Button_Click_1"
>Toggle Selected Item</
Button
>
</
StackPanel
>
</
Grid
>
</
Window
>
MainWindow,cs
public
partial
class
MainWindow : Window
{
private
bool
isItemSet =
false
;
public
object
Item
{
get
{
return
(
object
)GetValue(ItemProperty); }
set
{ SetValue(ItemProperty, value); }
}
// Using a DependencyProperty as the backing store for Item. This enables animation, styling, binding, etc...
public
static
readonly
DependencyProperty ItemProperty =
DependencyProperty.Register(
"Item"
,
typeof
(
object
),
typeof
(MainWindow),
new
UIPropertyMetadata(
null
));
public
bool
IsHidden
{
get
{
return
(
bool
)GetValue(IsHiddenProperty); }
set
{ SetValue(IsHiddenProperty, value); }
}
// Using a DependencyProperty as the backing store for IsHidden. This enables animation, styling, binding, etc...
public
static
readonly
DependencyProperty IsHiddenProperty =
DependencyProperty.Register(
"IsHidden"
,
typeof
(
bool
),
typeof
(MainWindow),
new
UIPropertyMetadata(
false
));
public
MainWindow()
{
InitializeComponent();
this
.DataContext =
this
;
}
private
void
Button_Click(
object
sender, RoutedEventArgs e)
{
IsHidden = !IsHidden;
}
private
void
Button_Click_1(
object
sender, RoutedEventArgs e)
{
if
(!isItemSet)
Item =
new
MyObject();
else
Item =
null
;
isItemSet = !isItemSet;
}
}
MyObject:
public
class
MyObject
{
[Display(Name =
"Name1"
, GroupName =
"Details1"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name1 {
get
;
set
; }
[Display(Name =
"Name2"
, GroupName =
"Details1"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name2 {
get
;
set
; }
[Display(Name =
"Name3"
, GroupName =
"Details2"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name3 {
get
;
set
; }
[Display(Name =
"Name4"
, GroupName =
"Details2"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name4 {
get
;
set
; }
[Display(Name =
"Name5"
, GroupName =
"Details2"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name5 {
get
;
set
; }
[Display(Name =
"Name6"
, GroupName =
"Details2"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name6 {
get
;
set
; }
[Display(Name =
"Name7"
, GroupName =
"Details2"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name7 {
get
;
set
; }
[Display(Name =
"Name8"
, GroupName =
"Details2"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name8 {
get
;
set
; }
[Display(Name =
"Name9"
, GroupName =
"Details2"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name9 {
get
;
set
; }
[Display(Name =
"Name10"
, GroupName =
"Details2"
, Order = 5, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name10 {
get
;
set
; }
[Display(Name =
"Name11"
, GroupName =
"Details3"
, Order = 6, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name11 {
get
;
set
; }
[Display(Name =
"Name12"
, GroupName =
"Details3"
, Order = 6, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name12 {
get
;
set
; }
[Display(Name =
"Name13"
, GroupName =
"Details3"
, Order = 6, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name13 {
get
;
set
; }
[Display(Name =
"Name14"
, GroupName =
"Details3"
, Order = 6, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name14 {
get
;
set
; }
[Display(Name =
"Name15"
, GroupName =
"Details3"
, Order = 6, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name15 {
get
;
set
; }
[Display(Name =
"Name16"
, GroupName =
"Details3"
, Order = 6, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name16 {
get
;
set
; }
[Display(Name =
"Name17"
, GroupName =
"Details4"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name17 {
get
;
set
; }
[Display(Name =
"Name18"
, GroupName =
"Details4"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name18 {
get
;
set
; }
[Display(Name =
"Name19"
, GroupName =
"Details4"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name19 {
get
;
set
; }
[Display(Name =
"Name20"
, GroupName =
"Details4"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name20 {
get
;
set
; }
[Display(Name =
"Name21"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name21 {
get
;
set
; }
[Display(Name =
"Name22"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name22 {
get
;
set
; }
[Display(Name =
"Name23"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name23 {
get
;
set
; }
[Display(Name =
"Name24"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name24 {
get
;
set
; }
[Display(Name =
"Name25"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name25 {
get
;
set
; }
[Display(Name =
"Name26"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name26 {
get
;
set
; }
[Display(Name =
"Name27"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name27 {
get
;
set
; }
[Display(Name =
"Name28"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name28 {
get
;
set
; }
[Display(Name =
"Name29"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name29 {
get
;
set
; }
[Display(Name =
"Name30"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name30 {
get
;
set
; }
[Display(Name =
"Name31"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name31 {
get
;
set
; }
[Display(Name =
"Name32"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name32 {
get
;
set
; }
[Display(Name =
"Name33"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name33 {
get
;
set
; }
[Display(Name =
"Name34"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name34 {
get
;
set
; }
[Display(Name =
"Name35"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name35 {
get
;
set
; }
[Display(Name =
"Name36"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name36 {
get
;
set
; }
[Display(Name =
"Name37"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name37 {
get
;
set
; }
[Display(Name =
"Name38"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name38 {
get
;
set
; }
[Display(Name =
"Name39"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name39 {
get
;
set
; }
[Display(Name =
"Name40"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name40 {
get
;
set
; }
[Display(Name =
"Name41"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name41 {
get
;
set
; }
[Display(Name =
"Name42"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name42 {
get
;
set
; }
[Display(Name =
"Name43"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name43 {
get
;
set
; }
[Display(Name =
"Name44"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name44 {
get
;
set
; }
[Display(Name =
"Name45"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name45 {
get
;
set
; }
[Display(Name =
"Name46"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name46 {
get
;
set
; }
[Display(Name =
"Name47"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name47 {
get
;
set
; }
[Display(Name =
"Name48"
, GroupName =
"Details5"
, Order = 7, Prompt =
"tttt"
), Browsable(
true
)]
public
string
Name48 {
get
;
set
; }
}
PropertiesControl.xaml:
<
UserControl
x:Class
=
"RadPropertyGridPerformanceIssue1.PropertiesControl"
xmlns:telerk
=
"http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable
=
"d"
d:DesignHeight
=
"300"
d:DesignWidth
=
"300"
>
<
Grid
>
<
telerk:RadPropertyGrid
Item
=
"{Binding Item}"
DescriptionPanelVisibility
=
"Collapsed"
/>
</
Grid
>
</
UserControl
>
If you click the first button and then the second button over and over again, then you would notice that the property grid becomes slower and slower, and that the Telerik.Windows.Data.WeakEvent+WeakListener`1.Handler() is being called more than once, event though OnCollectionChanged was called only once.
On Telerik 2016.Q2 the problem was even worse. The OnCollectionChanged would be called as the number of properties the object has.