Why do DbConnectionStringBuilder descendants break Property Grid binding so thoroughly?
See the question and my original answer on StackOverflowYes, there's a reason why a class deriving from DbConnectionStringBuilder has a special behavior when used with a property grid.
It's because it implements the ICustomTypeDescriptor Interface. In general, a property grid uses the TypeDescriptor.GetProperties method which will by default defer to ICustomTypeDescriptor if implemented.
What it means is a property grid will not use the compiled .NET/C# properties to represent an instance, but instead use the properties from the ICustomTypeDescriptor
interface, with custom PropertyDescriptor
instances.
So the compiled .NET/C# properties will not be used at all by a property grid, only "virtual" properties made up by the internal DbConnectionStringBuilder
code (you can check its code here https://github.com/microsoft/referencesource/blob/master/System.Data/System/Data/Common/DbConnectionStringBuilder.cs#L335). These "virtual" properties will be constructed using .NET compiled ones, but their code won't be used for getting or setting them.
This is in a way similar to WPF dependency properties feature where the compiled properties of a .NET class are just used by .NET code, not by the WPF binding/XAML engine (except WPF uses DependencyProperty.Register
code to define the dependency properties, not the compiled ones).
If you want to support the WPF binding engine, you can implement INotifyPropertyChanged
to your class like this for example:
public event PropertyChangedEventHandler PropertyChanged;
// thanks to how DbConnectionStringBuilder is designed,
// we can override this central method
public override object this[string keyword]
{
get => base[keyword];
set
{
object existing = null;
try
{
existing = base[keyword];
}
catch
{
// do nothing
}
if (existing == null)
{
if (value == null)
return;
}
else if (existing.Equals(value))
return;
base[keyword] = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(keyword));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ConnectionString)));
}
}
For existing classes such as this one: MySqlConnectionStringBuilder, there's nothing you can do (unless wrapping them with another class implementing ICustomTypeDescriptor
with an approach similar to this DynamicTypeDescriptor). Not every .NET class works fine with WPF binding or even the standard Winforms binding. And it's sealed...