When using the property grid, how can I get it to allow me to set one property for multiple objects at once (when there is a second level). Everything seems to work ok if both the properties have the same value, but if the properties are not equal the propertygrid does not load the sub properties (from the arrow to the right) so they can not be set. I have created the following example, sorry for the length of the code.
public partial class Form1 : Form
{
public Form1()
{
this.Size = new Size(275, 568);
PropertyGrid grid = new PropertyGrid();
grid.Dock = DockStyle.Fill;
this.Controls.Add(grid);
Control c1 = new Control();
c1.Border.Bottom.Color = Color.Red;
Control c2 = new Control();
c2.Border.Bottom.Color = Color.Red;
Control c3 = new Control();
c3.Border.Bottom.Color = Color.Purple;
//This works as expected
//grid.SelectedObject = c1;
//This works as expected
//grid.SelectedObjects = new object[] { c1, c2 };
//This does not work
grid.SelectedObjects = new object[] { c1, c3 };
}
}
class Control
{
public Control()
{
Border = new Border();
Text = "Text";
}
public string Text { get; set; }
[TypeConverter(typeof(BorderConverter))]
public Border Border { get; set; }
}
class Border
{
public Border()
{
Top = new Line();
Bottom = new Line();
Right = new Line();
Left = new Line();
}
[TypeConverter(typeof(LineConverter))]
public Line Top { get; set; }
[TypeConverter(typeof(LineConverter))]
public Line Left { get; set; }
[TypeConverter(typeof(LineConverter))]
public Line Bottom { get; set; }
[TypeConverter(typeof(LineConverter))]
public Line Right { get; set; }
public override bool Equals(object obj)
{
if ((obj as Border) == null)
return false;
Border b = (Border)obj;
return b.Left.Equals(Left) &&
b.Right.Equals(Right) && b.Top.Equals(Top)
&& b.Bottom.Equals(Bottom);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
public class BorderConverter
: TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return ((destinationType == typeof(InstanceDescriptor)) || base.CanConvertTo(context, destinationType));
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return attributes == null ? TypeDescriptor.GetProperties(value) : TypeDescriptor.GetProperties(value, attributes);
}
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
}
class Line
{
public Line()
{
Color = Color.Black;
Wieght = 0;
}
public Color Color { get; set; }
public int Wieght { get; set; }
public override bool Equals(object obj)
{
if ((obj as Line) == null)
return false;
Line l = (Line)obj;
return l.Color == Color && l.Wieght == Wieght;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
public class LineConverter
: TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return ((destinationType == typeof(InstanceDescriptor)) || base.CanConvertTo(context, destinationType));
}
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
{
if (propertyValues == null) throw new ArgumentNullException("propertyValues");
try
{
Line bs = new Line();
bs.Color = (Color)propertyValues["Color"];
bs.Wieght = (int)propertyValues["Wieght"];
return bs;
}
catch (Exception ex) { throw new Exception("Invalid Property value.", ex); }
}
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return attributes == null ? TypeDescriptor.GetProperties(value) : TypeDescriptor.GetProperties(value, attributes);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return base.GetStandardValuesSupported(context);
}
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
}
I managed to get it work by removing GetCreateInstanceSupported
method from LineConverter
, but I do not know exactly what is the main cause of your issue since I do not have extensive knowledge how PropertyGrid
is using TypeDescriptor
infrastructure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With