在UserControl中公开DataGridView的columns属性无法正常工作

时间:2016-02-09 06:19:04

标签: c# winforms datagridview user-controls

我在DataGridView中添加UserControl并在我的usercontrol中创建一个公共属性,公开datagridview的columns属性。
以下是示例代码:

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

    public DataGridViewColumnCollection MyDataGridColumns
    {
        get
        {
            return dataGridView1.Columns;
        }
    }
}

然后我在表单中添加UserControl1,然后在属性窗口中单击MyDataGridColumns属性并添加1个或更多列。 当我重建我的解决方案时会出现问题;我重新添加的所有列都会在重建后消失。

任何人都可以向我解释为什么会这样吗?以及如何解决?

2 个答案:

答案 0 :(得分:5)

这对我有用:我创建了一个特定的列编辑器,因为对于任何不扩展DataGridView的控件,似乎无法使用默认列编辑器。

public partial class UserControl1 : UserControl, IDataGridView
{
    public UserControl1()
    {
        InitializeComponent();
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [Browsable(false)]
    public DataGridView DataGridView
    {
        get { return dataGridView1; }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [Editor(typeof(ExtendedDataGridViewColumnCollectionEditor), typeof(UITypeEditor))]
    [MergableProperty(false)]
    public DataGridViewColumnCollection MyDataGridColumns
    {
        get { return dataGridView1.Columns; }
    }

}

public interface IDataGridView
{
    DataGridView DataGridView { get; }
}

class ExtendedDataGridViewColumnCollectionEditor : UITypeEditor
{
    private Form dataGridViewColumnCollectionDialog;

    private ExtendedDataGridViewColumnCollectionEditor() { }

    private static Form CreateColumnCollectionDialog(IServiceProvider provider)
    {
        var assembly = Assembly.Load(typeof(ControlDesigner).Assembly.ToString());
        var type = assembly.GetType("System.Windows.Forms.Design.DataGridViewColumnCollectionDialog");

        var ctr = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0];
        return (Form)ctr.Invoke(new object[] { provider });
    }

    public static void SetLiveDataGridView(Form form, DataGridView grid)
    {
        var mi = form.GetType().GetMethod("SetLiveDataGridView", BindingFlags.NonPublic | BindingFlags.Instance);
        mi.Invoke(form, new object[] { grid });
    }

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        if (provider != null && context != null)
        {
            var service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            if (service == null || context.Instance == null)
                return value;

            var host = (IDesignerHost)provider.GetService(typeof(IDesignerHost));
            if (host == null)
                return value;

            if (dataGridViewColumnCollectionDialog == null)
                dataGridViewColumnCollectionDialog = CreateColumnCollectionDialog(provider);

            //Unfortunately we had to make property which returns inner datagridview  
            //to access it here because we need to pass DataGridView into SetLiveDataGridView () method 
            var grid = ((IDataGridView)context.Instance).DataGridView;
            //we have to set Site property because it will be accessed inside SetLiveDataGridView () method 
            //and by default it's usually null, so if we do not set it here, we will get exception inside SetLiveDataGridView () 
            var oldSite = grid.Site;
            grid.Site = ((UserControl)context.Instance).Site;
            //execute SetLiveDataGridView () via reflection 
            SetLiveDataGridView(dataGridViewColumnCollectionDialog, grid);

            using (var transaction = host.CreateTransaction("DataGridViewColumnCollectionTransaction"))
            {
                if (service.ShowDialog(dataGridViewColumnCollectionDialog) == DialogResult.OK)
                    transaction.Commit();
                else
                    transaction.Cancel();
            }
            //we need to set Site property back to the previous value to prevent problems with serializing our control 
            grid.Site = oldSite;
        }

        return value;
    }

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }
}

答案 1 :(得分:2)

这是因为您没有指定列的类型。您应该在添加列时提供列的类型(例如DataGridViewTextBoxColumnDataGridViewCheckBoxColumn)。在Form1.cs执行以下操作:

public Form1()
{
    InitializeComponent();
    DataGridViewColumn dgViewColumn = new DataGridViewTextBoxColumn();//Or DataGridViewCheckBoxColumn
    dgViewColumn.DataPropertyName = "dgViewColumn";
    dgViewColumn.HeaderText = @"dgViewColumn";
    dgViewColumn.Name = "dgViewColumn";
    userControl11.MyDataGridColumns.Add(dgViewColumn);
}