Expose Columns property of a DataGridView in UserControl and make it editable via Designer

后端 未结 1 482
野趣味
野趣味 2020-12-06 13:29

Short description:

I have a UserControl with a DataGridView on it. I want to expose the DataGridView Columns collection to the designer, so I

相关标签:
1条回答
  • 2020-12-06 14:10

    Usually it's enough to register a suitable UITypeEditor using [Editor] attribute. The editor which is used by the DataGridView is DataGridViewColumnCollectionEditor. But in this case, if we use this editor directly, the editor expect the the property belong to a DataGridView and tries to convert value of ITypeDescriptorContext.Instance to DataGridVeiew and since our editing Columns property belongs to our user control we will receive an exception:

    Unable to cast object of type 'Type of Control' to type 'System.Windows.Forms.DataGridView'.

    To solve the problem, we need to create a custom UITypeEditor and override EditValue and edit Columns property of the private DataGridView field of your user control.

    To do so, we create an instance of ITypeDescriptorContext containing the DataGridView and it's Columns property and pass it to EditValue method of the editor. This way the editor will edit our Columns property.

    We also decorate our property using [DesignerSerializationVisibility] attribute to serialize the collection contents.

    Here is the implementations.

    MyUserControl

    I suppose you add a DataGridView at design-time to the user control and its name would be dataGridView1.

    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();
        }
    
        [Editor(typeof(MyColumnEditor), typeof(UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public DataGridViewColumnCollection Columns
        {
            get { return this.dataGridView1.Columns; }
        }
    }
    

    Editor

    public class MyColumnEditor : UITypeEditor
    {
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.Modal;
        }
        public override object EditValue(ITypeDescriptorContext context,
                                         IServiceProvider provider, object value)
        {
            var field = context.Instance.GetType().GetField("dataGridView1",
                           System.Reflection.BindingFlags.NonPublic |
                           System.Reflection.BindingFlags.Instance);
    
            var dataGridView1 = (DataGridView)field.GetValue(context.Instance);
            dataGridView1.Site = ((Control)context.Instance).Site;
            var columnsProperty = TypeDescriptor.GetProperties(dataGridView1)["Columns"];
            var tdc = new TypeDescriptionContext(dataGridView1, columnsProperty);
            var editor = (UITypeEditor)columnsProperty.GetEditor(typeof(UITypeEditor));
            var result = editor.EditValue(tdc, provider, value);
            dataGridView1.Site = null;
            return result;
        }
    }
    

    ITypeDescriptionContext Implementation

    public class TypeDescriptionContext : ITypeDescriptorContext
    {
        private Control editingObject;
        private PropertyDescriptor editingProperty;
        public TypeDescriptionContext(Control obj, PropertyDescriptor property)
        {
            editingObject = obj;
            editingProperty = property;
        }
        public IContainer Container
        {
            get { return editingObject.Container; }
        }
        public object Instance
        {
            get { return editingObject; }
        }
        public void OnComponentChanged()
        {
        }
        public bool OnComponentChanging()
        {
            return true;
        }
        public PropertyDescriptor PropertyDescriptor
        {
            get { return editingProperty; }
        }
        public object GetService(Type serviceType)
        {
            return editingObject.Site.GetService(serviceType);
        }
    }
    
    0 讨论(0)
提交回复
热议问题