Alternatives to PropertyGrid

I like PropertyGrid, well, at least the concept underlying this is to use reflection and attributes to edit your objects, don't write a lot of user interface code.

My excitement died pretty quickly, although, by default, the PropertyGrid shipped with WinForms is flat. Well, this is great for editing simple objects, etc., but as for that.

  • It does not display the corresponding UITypeEditors for dynamic properties that are of the Object type.
  • Once your objects contain collections, you can edit them using the so-called CollectionEditor. However, it will not fire the PropertyValueChanged event. Therefore, when you need to add undo functionality, you are screwed.
  • And I still haven't found an elegant way to add validation for CollectionEditor.
  • It is also problematic to implement undo if you select multiple objects, because in this case the arguments to PropertyValueChanged ChangedItem are null.

I soon discovered that I was writing hacks to solve these problems with less pleasant results.

What would you do? Is there an elegant solution to at least the first three questions? Is there an alternative propertygrid? Preferably free and without PInvokes?

+7
c # winforms propertygrid
source share
3 answers

Most of the elegance of PropertyGrid comes from its simplicity. First of all, it is intended for pleasant communication with Visual Studio, and I expect to see that it is used mainly in custom UITypeEditor and extensions, and not in the application code.

Presumably the objects you attach to the PropertyGrid are classes of your own design? I found that in order to make good use of the property grid, you must pretty much decorate your classes and members with attributes.

You may find some joy in writing your own CollectionEditor subclasses (and other types of editors) and attaching them to class members using the [Editor] attribute - if you can attach this attribute to your dynamic properties, you can force the use of a specific editor.

The only way I can add validation to CollectionEditor is to override the CreateCollectionForm() method, returning an instance of your own custom subclass of CollectionEditor.CollectionForm . There is a chance that you can trigger change events here.

Unfortunately, all I can do is nod and agree with the statement to cancel the cancellation. You may need to resort to "backing up" affected objects by cloning or serializing to implement undo.

I have seen alternatives to the built-in network control, but they exist mainly for creating different visual styles.

+5
source share

If anyone is interested, here is a workaround for the PropertyValueChanged problem, which mimics the change by calling the MemberwiseClone function of the System.Object if CollectionEditor PropertyValueChanged was run ...

 public class FixedCollectionEditor : CollectionEditor { bool modified; public FixedCollectionEditor(Type type) : base(type) { } public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value) { value = base.EditValue(context, provider, value); if (value != null && modified) { value = value.GetType() .GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic) .Invoke(value, new object[] { }); } modified = false; return value; } protected override CollectionForm CreateCollectionForm() { CollectionForm collectionForm = base.CreateCollectionForm(); foreach (Control table in collectionForm.Controls) { if (!(table is TableLayoutPanel)) { continue; } foreach (Control c1 in table.Controls) { if (c1 is PropertyGrid) { PropertyGrid propertyGrid = (PropertyGrid)c1; propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(GotModifiedHandler); } if (c1 is TableLayoutPanel) { foreach (Control c2 in c1.Controls) { if (!(c2 is Button)) { continue; } Button button = (Button)c2; if (button.Name == "addButton" || button.Name == "removeButton") { button.Click += new EventHandler(GotModifiedHandler); if (button.ContextMenuStrip != null) { button.ContextMenuStrip.ItemClicked += new ToolStripItemClickedEventHandler(GotModifiedHandler); } } } } } } return collectionForm; } void GotModifiedHandler(object sender, EventArgs e) { modified = true; } } 
+2
source share

Visualhint is selling a property grid replacement that may help. Since I never used it in a real project, I don’t know how much it works.

+1
source share

All Articles