Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the property grid to allow the edit of objects for multi select

Tags:

c#

.net

winforms

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;
    }
}  
like image 665
Matthew Sanford Avatar asked Nov 03 '22 23:11

Matthew Sanford


1 Answers

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.

like image 153
Stipo Avatar answered Nov 12 '22 13:11

Stipo