views:

109

answers:

3

I have a project in that we have to represent some graphic objects on a usercontrol in WYSIWYG. Also is required to edit each objects properties(Color, Location, etc).

alt text

I hesitate between using PropertyGrid ('direct' properties edit) and custom forms on DoubleClick ('indirect' edit).

The PropertyGrid is very well but should correspond a some criteria:

  • Only selected properties are Displayed (by e.g. if I have TextRectangle want display only Text and Location);
  • Property names should be customizable and internationalizable (by e.g. TextRectangle Text property should be named "Company Name" or "Название предприятия").

Now about is it possible I think the answer could be Yes, but is it reasonable to use it if we have not a lot of time. What could be quicker implemented, custom forms or Property panel?

EDIT:
The most examples I saw on internet was with totally custom objects witch properties can be easy managed. The problem I have is that I would display also ready .NET Framework objects that I can't control like TextBoxes, Label, RectangleShape or OvalShape(VB.Powerpacks)

Is there a possibility to hide all properties and only indicate a few ones that should be present?

+1  A: 

The property grid will check the selected objects properties for certain attributes:

This means that you can hide some properties and partially control how the properties are displayed, but you can't add custom or translated property names as far as I know.

Check the docs on MSDN for more information.

Edit: You should check out this article on Codeproject about a globalized property grid. It seems to do what you are after.

Rune Grimstad
Attributes can be used for properties that the object overrides or has. Now, How could I hide the properties that object inherits. "Visible" or "RightToLeft" or "TabIndex"... DescriptionAttribute is not internationalizable.
serhio
GlobalizedPropertyGrid seems o be good, but what if the object I have is not a custom object, but a framework one like TextBox... where I have a lot of properties that I can't modify to add attributes.
serhio
+2  A: 

PropertyGrid is customizable using attributes on the displayed classes.

Using a TypeConverter you can control the look & feel of properties and/or objects in the PropertyGrid. You can use it to add "virtual" properties, or leave properties out. Also the name of the property can be changed / localized. But a Typeconverter is somewhat harder to implement as the other options.

With the UITypeEditor you can control how a property should be edited (inline, show your own dialog, colorpicker, ...)

You can attach a DisplayName to a property, to change the name. If you override the class, you can translate the propertynames. This question has an example how to do this.

And (like Rune Grimstad answered) you leave out properties by putting a [Browsable(false)] attribute on them.

Another nice one is the DefaultValue, if the value of an attribute matches the value provided by the DefaultValue, the value uses the normal font. If it differs it uses a Bold font.

Your problem is that you do not want to inherit from TextBox or other classes all the time. You can encapsulate the Textbox in a wrapper, that only exposes (via a TypeConverter) the properties you need. I've hacked something that does this:

class BaseWrapper<T> {
    public BaseWrapper(T tb) {
        this.Wrapped = tb;
    }

    [Browsable(false)]
    public T Wrapped { get; set; }

    public object GetMember(string name) {
        var prop = this.Wrapped.GetType().GetProperty(name);
            return prop.GetValue(this.Wrapped, null);
    }

    public void SetMember(string name, object value) {
        var prop = this.Wrapped.GetType().GetProperty(name);
        prop.SetValue(this.Wrapped, value, null);
    }
}

class BaseConverter<T> : TypeConverter {
    protected class pd : SimplePropertyDescriptor {
        public pd(string displayName, string name) : base(typeof(BaseWrapper<T>), displayName, typeof(string)) {
            this.PropName = name;

        }
        public string PropName { get; set; }

        public override object GetValue(object component) {
            var wrapper = (BaseWrapper<T>)component;
            return wrapper.GetMember(this.PropName);
        }
        public override void SetValue(object component, object value) {
            var wrapper = (BaseWrapper<T>)component;
            wrapper.SetMember(this.PropName, value);
        }
    }
    public override bool GetPropertiesSupported(ITypeDescriptorContext context) {
        return true;
    }
}

[TypeConverter(typeof(TextBoxConverter))]
class TextboxWrapper : BaseWrapper<TextBox> {
    public TextboxWrapper(TextBox t) : base(t) { }
}

class TextBoxConverter : BaseConverter<TextBox> {
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) {
        return new PropertyDescriptorCollection(new PropertyDescriptor[] {
            new pd("Название предприятия", "Text")
        });
    }
}

To make a textbox the selected object, you use:

this.propertyGrid1.SelectedObject = new TextboxWrapper(this.textBox1);

The place to further work this out is in the pd (ugly name, I know) class, to include the data type, and a localized labels.

GvS
beside the look and feel I need to filter the selected properties and internationalize them.
serhio
I've updated my answer, I think you can find what you need.
GvS
Not every property can be overrided. If I use standarrd TextBox I need I to override every inherited overridable and not overridable properties of TextBox:Control...
serhio
Or implement your own TypeConverter, you can create your own list of properties to show. Override `GetProperties`, call the base, and remove the properties you do not want.
GvS
A: 

You might look at this article on CodeProject. It uses a generic PropertyBag object to contain whatever properties you want to expose from your object(s) and gives the PropertyBag to the PropertyGrid to display.