PropertyGrid替代品

时间:2010-08-24 21:23:53

标签: c# .net winforms propertygrid

我喜欢PropertyGrid,至少它背后的概念 - 使用反射和属性来编辑你的对象,而无需编写很多UI代码。

我的兴奋很快就消失了,默认的带有WinForms的默认PropertyGrid也很糟糕。好吧,它可以用于编辑简单的对象等等,但这就是它的最佳状态。

  • 对于类型为“Object”的动态属性,它不显示适当的UITypeEditors。
  • 只要您的对象包含集合,您就可以使用所谓的CollectionEditor编辑它们。但是,它不会触发PropertyValueChanged事件。因此,一旦你需要添加撤消功能,你就搞砸了。
  • 我还没有找到一种优雅的方法来为CollectionEditor添加验证。
  • 如果选择了多个对象,则实现撤销也会出现问题,因为在这种情况下,PropertyValueChanged事件args ChangedItem为空。

我很快就发现自己正在编写黑客来解决这些问题而不是那么令人满意的结果。

你会做什么? 至少前三个问题是否有优雅的解决方案? 有替代的属性网格吗?优选地,免费和没有PInvokes?

3 个答案:

答案 0 :(得分:5)

很多PropertyGrid的优雅来自它的简洁。最重要的是,它的设计与Visual Studio相得益彰,我希望它主要用于自定义UITypeEditor和扩展,而不是应用程序代码。

您附加到PropertyGrid的对象可能是您自己设计的类?我发现,为了充分利用属性网格,你必须用属性大量装饰你的类和成员。

您可以在编写自己的CollectionEditor子类(以及其他类型的编辑器)并使用[Editor]属性将其附加到类成员时感到高兴 - 如果您可以将此属性附加到动态属性,您可以强制使用特定的编辑器。

我能想到向CollectionEditor添加验证的唯一方法是覆盖CreateCollectionForm()方法,返回自己的自定义子类CollectionEditor.CollectionForm的实例。你有可能从这里开始改变事件。

不幸的是,我能做的只是点头并同意关于实现撤销的断言。您可能不得不通过克隆或序列化来“备份”受影响的对象,以实现撤消。

我见过内置属性网格控件的替代品,但它们的存在主要是为了提供不同的视觉风格。

答案 1 :(得分:2)

如果有人感兴趣 - 这是PropertyValueChanged问题的解决方法,如果CollectionEditor的PropertyValueChanged被触发,则通过调用System.Object的MemberwiseClone函数来模拟更改...

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 :(得分:1)

Visualhint出售可能有帮助的房产网格的替代品。由于我从未在实际项目中使用它,我不知道它的工作情况如何。