在 UserControl 中公开 DataGridView 的 Columns 属性并通过设计器使其可编辑 [英] Expose Columns property of a DataGridView in UserControl and make it editable via Designer

查看:25
本文介绍了在 UserControl 中公开 DataGridView 的 Columns 属性并通过设计器使其可编辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简短说明:

我有一个带有 DataGridView 的 UserControl.一世想要将 DataGridView Columns 集合公开给设计器,所以我可以在设计时更改用户控件上的列.

I have a UserControl with a DataGridView on it. I want to expose the DataGridView Columns collection to the designer, so I can change the columns on my User Control at design time.

问题:我需要哪些设计师属性?

对于那些对更长版本感兴趣的人:

For those interested in the longer version:

我有一个具有以下功能的 UserControl:

I have a UserControl with the following features:

  • 显示集合中项目的页面"的 DataGridView.
  • 一个 NumericUpdown 控件,用于选择要显示的页面.
  • 在显示第一页/最后一页时将禁用的向上/向下翻页按钮
  • 对显示项目的更改以视觉方式标记
  • 保存/放弃更改的按钮.

此用户控件可以自主工作.它有一个供父控件使用的功能:

This user control can work autonomic. It has one function to be used by the parent control:

  • 显示页面(要显示的项目集合)

UserControl 引发两个事件:

The UserControl raises two events:

  • 活动页面已更改(带有页码).应该会导致加载新页面
  • 事件保存项目(包含已更改项目的集合)

我必须在几个表单上显示这个用户控件.唯一的区别是 DataGridViewColumn 的集合因表单而异.

I have to show this user control on several forms. The only difference is that the collection of DataGridViewColumn differs per form.

我可以通过编程方式添加列,但使用设计器创建它们会更容易.

I could add the columns programmatically, but it would be easier to create them using the designer.

推荐答案

通常注册一个合适的就足够了 UITypeEditor 使用 属性.DataGridView 使用的编辑器是DataGridViewColumnCollectionEditor.但是在这种情况下,如果我们直接使用这个编辑器,编辑器会期望该属性属于一个 DataGridView 并尝试转换 ITypeDescriptorContext.InstanceDataGridVeiew 并且由于我们的编辑 Columns 属性属于我们的用户控件,我们将收到一个异常:

Usually it's enough to register a suitable UITypeEditor using 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:

无法将 'Type of Control' 类型的对象转换为类型'System.Windows.Forms.DataGridView'.

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

要解决这个问题,我们需要创建一个自定义 UITypeEditor 并覆盖 EditValue 并编辑 ColumnsDataGridView 字段的 code> 属性.

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.

为此,我们创建了一个 ITypeDescriptorContext 包含 DataGridView 和它的 Columns 属性并传递它到编辑器的 EditValue 方法.这样编辑器将编辑我们的 Columns 属性.

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.

我们还使用 [DesignerSerializationVisibility] 属性来序列化集合内容.

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

这里是实现.

MyUserControl

我假设您在设计时将 DataGridView 添加到用户控件,其名称将是 dataGridView1.

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

编辑器

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 实现

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

这篇关于在 UserControl 中公开 DataGridView 的 Columns 属性并通过设计器使其可编辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆