Search code examples
vb.netdatagridviewuitypeeditor

Error open "Edit Columns" when click property in UserControl


VB.Net

i have a UserControl with Dgv1(DataGridView)

i want edit Columns in design with "Edit Columns" Form

Cod UserControl:

Public Class MyUserControl
    Inherits UserControl


    <Editor(GetType(MyColumnEditor), GetType(UITypeEditor))> _
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    Public ReadOnly Property Columns() As DataGridViewColumnCollection
        Get
            Return Me.Dgv1.Columns

        End Get
    End Property


End Class

MyColumnEditor:

Public Class MyColumnEditor
    Inherits System.Drawing.Design.UITypeEditor

    Public Overrides Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
        Return UITypeEditorEditStyle.Modal
    End Function

    Public Overloads Overrides Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As Object) As Object

        Dim field As Object = context.Instance.[GetType]().GetField("Dgv1", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)

        Dim dataGridView1 = CType(field.GetValue(context.Instance), DataGridView)
        dataGridView1.Site = CType(context.Instance, Control).Site
        Dim columnsProperty As Object = TypeDescriptor.GetProperties(dataGridView1)("Columns")
        Dim tdc As Object = New TypeDescriptionContext(dataGridView1, columnsProperty)
        Dim editor = CType(columnsProperty.GetEditor(GetType(UITypeEditor)), UITypeEditor)
        Dim result As Object = editor.EditValue(tdc, provider, value)
        dataGridView1.Site = Nothing
        Return result

    End Function
End Class

TypeDescriptionContext:

Public Class TypeDescriptionContext
    Implements ITypeDescriptorContext

    Public editingObject As Control
    Public editingProperty As PropertyDescriptor
    Public Sub New(obj As Control, property1 As PropertyDescriptor)
        editingObject = obj
        editingProperty = property1
    End Sub

    Public ReadOnly Property Container As IContainer Implements ITypeDescriptorContext.Container
        Get
            Return editingObject.Container
        End Get
    End Property

    Public ReadOnly Property Instance As Object Implements ITypeDescriptorContext.Instance
        Get
            Return editingObject

        End Get
    End Property

    Public Sub OnComponentChanged() Implements ITypeDescriptorContext.OnComponentChanged

    End Sub

    Public Function OnComponentChanging() As Boolean Implements ITypeDescriptorContext.OnComponentChanging
        Return True

    End Function

    Public ReadOnly Property PropertyDescriptor As PropertyDescriptor Implements ITypeDescriptorContext.PropertyDescriptor
        Get
            Return editingProperty
        End Get
    End Property

    Public Function GetService(serviceType As Type) As Object Implements IServiceProvider.GetService
        Return editingObject.Site.GetService(serviceType)
    End Function
End Class

but when click Columns Property for edit show Error: Object variable or With block variable not set.

https://i.sstatic.net/rkeua.jpg

And

The same code in C#: ,It works properly

UserControl:

public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();
        }

        [Editor(typeof(MyColumnEditor), typeof(UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public DataGridViewColumnCollection Columns
        {
            get { return this.Dgv1.Columns; }
        }
    }

MyColumnEditor:

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("Dgv1",
                           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;
        }
    }

TypeDescriptionContext:

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);
        }
    }

I know the Vb.net and not a professional And converted this code C# to VB.net

Where is the problem? Thanks in advance for your help


Solution

  • I found the problem

    In VB.Net When Add Datagridview to UserControl in Designer Cod Is defined has:

    Friend WithEvents Dgv1 As System.Windows.Forms.DataGridView
    

    That's right

    Private Dgv1 As System.Windows.Forms.DataGridView
    

    Even should not be like that

    Private WithEvents Dgv1 As System.Windows.Forms.DataGridView
    

    It's too bad

    I decided to move to C#