在UserControl中公开DataGridView的Columns属性,并通过Designer

时间:2016-04-22 07:17:05

标签: c# winforms datagridview user-controls windows-forms-designer

  

简短说明:

     

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

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

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

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

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

此用户控件可以自动运行。它有一个由父控件使用的函数:

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

UserControl引发了两个事件:

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

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

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

1 个答案:

答案 0 :(得分:3)

通常使用UITypeEditor属性注册合适的Editor就足够了。 DataGridView使用的编辑器是DataGridViewColumnCollectionEditor。但在这种情况下,如果我们直接使用此编辑器,编辑器会期望该属性属于DataGridView,并尝试将ITypeDescriptorContext.Instance的值转换为DataGridVeiew,因为我们正在编辑{{1属性属于我们的用户控件,我们将收到一个异常:

  

无法将' Columns类型的对象强制转换为类型   ' Type of Control''

要解决此问题,我们需要创建自定义System.Windows.Forms.DataGridView并覆盖UITypeEditor并修改用户控件的私有EditValue字段的Columns属性。

为此,我们创建了一个DataGridView的实例,其中包含ITypeDescriptorContext及其DataGridView属性,并将其传递给编辑器的Columns方法。这样编辑器就会编辑我们的EditValue属性。

我们还使用Columns属性装饰我们的属性以序列化集合内容。

以下是实施。

<强>的MyUserControl

我想您在设计时向用户控件添加[DesignerSerializationVisibility],其名称为DataGridView

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

ITypeDescriptionContext实施

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