【问题标题】:How to add support of multiobject edits for PropertyGrid's custom property editor?如何为 PropertyGrid 的自定义属性编辑器添加对多对象编辑的支持?
【发布时间】:2015-05-23 14:44:20
【问题描述】:

这是有史以来最简单的自定义属性编辑器,仅包含一个带有多个 PropertyGrid 的表单:

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms.Design;

namespace PageControls
{
    public partial class PropertyGridEditor : Form
    {
        public object ObjectToEdit;

        public delegate void PropertyValueChangedEventHandler(object sender, PropertyValueChangedEventArgs e);
        public static event PropertyValueChangedEventHandler PropertyValueChangedStatic;
        public event EventHandler<PropertyValueChangedEventArgs> PropertyValueChanged;

        public PropertyGridEditor(object obj_to_edit)
        {
            InitializeComponent();
            this.ObjectToEdit = obj_to_edit;
        }

        private void PropertyGridEditor_Load(object sender, EventArgs e)
        {
            this.prop_grid.SelectedObject = ObjectToEdit;
        }

        private void PropertyGridEditor_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private void prop_grid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            var evt = PropertyGridEditor.PropertyValueChangedStatic;

            if (evt != null)
                evt(s, e);

            var evt2 = this.PropertyValueChanged;

            if (evt2 != null)
                evt2(s, e);
        }
    }

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
    public class InnerPropertyGridEditor : UITypeEditor
    {
        public InnerPropertyGridEditor()
        {

        }

        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            // Indicates that this editor can display a Form-based interface. 
            return UITypeEditorEditStyle.Modal;
        }

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            // Attempts to obtain an IWindowsFormsEditorService.
            IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

            if (edSvc == null)
                return null;

            using (PropertyGridEditor form = new PropertyGridEditor(value)) //when two or more properties were selected the value is null :/
                if (edSvc.ShowDialog(form) == DialogResult.OK)
                    return form.ObjectToEdit;

            return value; // If OK was not pressed, return the original value 
        }
    }
}

所以,现在我有课了:

class Test
{
   public bool Prop1 { get; set; }
   public bool Prop2 { get; set; }
}

我的主类有这个Test 类作为属性。

class MainClass
{
    [Editor(typeof(InnerPropertyGridEditor), typeof(UITypeEditor))]
    public Test test_prop { get; set; }

    ...
}

我的主 PropertyEditor 支持多选对象。 因此,我可以选择两个或多个 MainClass 来编辑它们的属性。

问题是 - 当我这样做并尝试编辑 test_prop InnerPropertyGridEditor 时显示为空,因为传递的值为空。

其实,我希望它至少是object[],这样我才能实现一些东西。

【问题讨论】:

    标签: c# .net properties multi-select propertygrid


    【解决方案1】:

    好的,如果没有人会回答这个问题,我将展示我提出的 hacky 解决方案:

    using System;
    using System.Windows.Forms;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Windows.Forms.Design;
    using System.Reflection;
    
    namespace PageControls
    {
        public partial class PropertyGridEditor : Form
        {
            public object Result;
    
            public static event EventHandler<PropertyValueChangedEventArgs> PropertyValueChangedStatic;
            public event EventHandler<PropertyValueChangedEventArgs> PropertyValueChanged;
    
            public PropertyGridEditor(object[] obj_to_edit)
            {
                InitializeComponent();
    
                this.prop_grid.SelectedObjects = obj_to_edit;
    
                this.Result = obj_to_edit[0];
            }
    
            private void PropertyGridEditor_Load(object sender, EventArgs e)
            {
    
            }
    
            private void PropertyGridEditor_FormClosed(object sender, FormClosedEventArgs e)
            {
                this.DialogResult = System.Windows.Forms.DialogResult.OK;
            }
    
            private void prop_grid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
            {
                var evt = PropertyGridEditor.PropertyValueChangedStatic;
    
                if (evt != null)
                    evt(s, e);
    
                var evt2 = this.PropertyValueChanged;
    
                if (evt2 != null)
                    evt2(s, e);
            }
        }
    
        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
        public class InnerPropertyGridEditor : UITypeEditor
        {
            public InnerPropertyGridEditor()
            {
    
            }
    
            public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
            {
                // Indicates that this editor can display a Form-based interface. 
                return UITypeEditorEditStyle.Modal;
            }
    
            public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
            {
                // Attempts to obtain an IWindowsFormsEditorService.
                IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
    
                if (edSvc == null)
                    return null;
    
                object[] values = new object[context.Instance is object[] ? ((object[])context.Instance).Length : 1];
    
                if (context.Instance is object[])
                    for (int i = 0; i < ((object[])context.Instance).Length; i++)
                    {
                        PropertyInfo pi = ((object[])context.Instance)[i].GetType().GetProperty(context.PropertyDescriptor.Name);
                        values[i] = pi != null ? pi.GetValue(((object[])context.Instance)[i], null) : null;
                    }
                else
                    values[0] = value;
    
                using (PropertyGridEditor form = new PropertyGridEditor(values))
                    if (edSvc.ShowDialog(form) == DialogResult.OK)
                        return form.Result;
    
                return value; // If OK was not pressed, return the original value 
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-27
      • 2013-03-25
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多