-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
.NET version
10.0.100-preview (also affects .NET 9)
Did it work in .NET Framework?
Yes
Did it work in any of the earlier releases of .NET Core or .NET 5+?
Yes, worked correctly in .NET 8 and earlier.
Issue description
PropertyGrid.SelectedObjects silently fails (shows empty grid) when assigned a typed array (e.g., ItemTypeDescriptor[]) instead of object[] in multi-select scenarios. The internal ArrayTypeMismatchException is swallowed, making this bug difficult to diagnose.
The bug only occurs when PropertySort is set to NoSort.
Root cause: In MultiSelectRootGridEntry.GetMergedProperties(), the NoSort code path calls objects.AsSpan(1). However, Span<T> is not covariant - when AsSpan<object>() is called on an array whose runtime type is MyClass[] (not object[]), it throws ArrayTypeMismatchException.
// In MultiSelectRootGridEntry.GetMergedProperties():
if ((sort & PropertySort.Alphabetical) != 0)
{
// This path does NOT use AsSpan - works fine
commonProperties = GetCommonProperties(objects, presort: true, tab, parentEntry);
}
else
{
// NoSort path - USES AsSpan - FAILS with typed arrays!
properties = GetCommonProperties(objects.AsSpan(1), presort: true, tab, parentEntry);
firstProperties = GetCommonProperties(objects.AsSpan(0, 1), presort: false, tab, parentEntry);
}The root cause can be demonstrated standalone:
object[] arr = new MyClass[] { new MyClass() }; // Covariant assignment - compiles fine
arr.AsSpan(); // Throws ArrayTypeMismatchException!Workaround: Use object[] explicitly instead of typed arrays:
// Instead of: var descriptors = new ItemTypeDescriptor[] { ... };
var descriptors = new object[] { new ItemTypeDescriptor(...), new ItemTypeDescriptor(...) };
propertyGrid.SelectedObjects = descriptors;Steps to reproduce
- Create a WinForms application targeting .NET 9 or .NET 10
- Create a
CustomTypeDescriptor-derived class (commonly used for property localization/filtering) - Set
PropertyGrid.PropertySort = PropertySort.NoSort - Create a typed array of descriptors and assign to
SelectedObjects - Observe: PropertyGrid is empty (no properties shown)
- Change to
object[]array - properties appear correctly
public class ItemTypeDescriptor : CustomTypeDescriptor
{
private readonly WeakReference _component;
public object? Component => _component.Target;
public ItemTypeDescriptor(object component, ICustomTypeDescriptor parent)
: base(parent)
{
_component = new WeakReference(component);
}
public override PropertyDescriptorCollection GetProperties()
=> base.GetProperties();
public override object? GetPropertyOwner(PropertyDescriptor? pd)
=> Component;
}
// Setup
propertyGrid.PropertySort = PropertySort.NoSort;
var model1 = new MyModel { Name = "Object1" };
var model2 = new MyModel { Name = "Object2" };
// BUG - typed array results in empty PropertyGrid:
var descriptors = new ItemTypeDescriptor[]
{
new ItemTypeDescriptor(model1, TypeDescriptor.GetProvider(model1).GetTypeDescriptor(model1)!),
new ItemTypeDescriptor(model2, TypeDescriptor.GetProvider(model2).GetTypeDescriptor(model2)!)
};
propertyGrid.SelectedObjects = descriptors; // PropertyGrid shows empty!
// WORKAROUND - object[] works correctly:
var descriptors = new object[]
{
new ItemTypeDescriptor(model1, TypeDescriptor.GetProvider(model1).GetTypeDescriptor(model1)!),
new ItemTypeDescriptor(model2, TypeDescriptor.GetProvider(model2).GetTypeDescriptor(model2)!)
};
propertyGrid.SelectedObjects = descriptors; // Properties are visible!Minimal repro project attached.