I have a PropertyGrid
whose selected object contains multiple properties with [DisplayName]
s of "Speed", all in different categories (the real property names in the code are of course all unique). I've noticed that if I have (for example) Speed #3 selected and PropertyGrid.Refresh()
is called, the selection will automatically move to Speed #1. What's more, the value of Speed #3 will sometimes be shown next to Speed #1 too. The situation resolves itself as soon as I click the grid and change the selection, but it's obviously not desired behavior.
I am currently hacking around this by adding different numbers of \t
characters to the DisplayName
s to make them all unique. This is an acceptable workaround since the tab characters aren't actually rendered, but I'd of course prefer not to have to do it.
Is there a rule that all DisplayName
s must be unique or is this a bug in PropertyGrid
?
Update: Since someone's bound to ask for a code sample, stick one of these in a PropertyGrid
and then call Refresh()
on it from a timer every two seconds or so:
class Demo
{
[Category("Cat1")]
[DisplayName("Speed")]
public int Speed1 { get; set; }
[Category("Cat2")]
[DisplayName("Speed")]
public int Speed2 { get; set; }
[Category("Cat3")]
[DisplayName("Speed")]
public int Speed3 { get; set; }
}
I don't think it's a bug, it's probably a feature (with side effects :-). You can check the property grid source on Microsoft site. The relevant portion seems this in GridEntry.cs code:
public override bool Equals(object obj) {
if (NonParentEquals(obj)) {
return((GridEntry)obj).ParentGridEntry == this.ParentGridEntry;
}
return false;
}
internal virtual bool NonParentEquals(object obj) {
if (obj == this) return true;
if (obj == null) return false;
if (!(obj is GridEntry)) return false;
GridEntry pe = (GridEntry)obj;
return pe.PropertyLabel.Equals(this.PropertyLabel) &&
pe.PropertyType.Equals(this.PropertyType) && pe.PropertyDepth == this.PropertyDepth;
}
As you see, it's the PropertyLabel which is used. If you follow the code a bit more, the label will ultimately use the property's DisplayName (or the name if the DisplayName attribute is not defined).