Designer 不序列化 UserControl 的 DataGridView 属性 的列
Designer doesn't serialzie Columns of a DataGridView property of a UserControl
我正在尝试创建一个包含标签、工具条和 Datagridview 的自定义控件。
当测试表单生成设计代码时,它会正确保存工具条项目,但不会保存 Datagridview 列。
代码DGrid.cs
...
[DesignerAttribute(typeof(MultiDesigner))]
public partial class FDGrid : Panel
{
....
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Category("Bars"), Description("Barra dei comandi.")]
public ToolStrip Barra
{
get { return _barra; }
set { _barra = value; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Category("Grid"), Description("Griglia dati.")]
public DataGridView Griglia
{
get { return _griglia; }
set { _griglia = value; }
}
....
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name =
"FullTrust")]
public class MultiDesigner : System.Windows.Forms.Design.ControlDesigner
{
public override void Initialize(IComponent c)
{
base.Initialize(c);
FDGrid ctl = (FDGrid)c;
EnableDesignMode(ctl.Griglia, "Griglia");
EnableDesignMode(ctl.Barra, "Barra");
}
}
...
代码FDGrid.Designer.cs
FDGrid.Designer.cs
....
private FDLabeledImage _titolo;
private ToolStrip _barra;
private DataGridView _griglia;
private void InitializeComponent()
{
this._barra = new System.Windows.Forms.ToolStrip();
this._griglia = new System.Windows.Forms.DataGridView();
this._titolo = new FDControl.FDLabeledImage();
((System.ComponentModel.ISupportInitialize)(this._griglia)).BeginInit();
this.SuspendLayout();
....
((System.ComponentModel.ISupportInitialize)(this._griglia)).EndInit();
this.ResumeLayout(false);
}
.....
代码Form1.Designer.cs
....
private void InitializeComponent()
{
this.fdGrid1 = new FDControl.FDGrid(); // OK
this.fdGrid1.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); **// Error**
this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel(); //OK
}
...
private FDControl.FDGrid fdGrid1; //OK
private System.Windows.Forms.ToolStripLabel toolStripLabel1; //OK
private System.Windows.Forms.DataGridViewTextBoxColumnfdGrid1.Column1;//Error
...
求助,我想明白我哪里错了?
不是最优雅的,但可行的解决方案:
创建自定义 MyDataGridView
派生自 DataGridView
:
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.Design;
public class MyDataGridView : DataGridView
{
[Editor(typeof(ExtendedDataGridViewColumnCollectionEditor), typeof(UITypeEditor))]
public new DataGridViewColumnCollection Columns { get => base.Columns; }
private 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 ctor = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0];
return (Form)ctor.Invoke(new object[] { provider });
}
public static void SetLiveDataGridView(Form form, DataGridView dgv)
{
var method = form.GetType().GetMethod("SetLiveDataGridView", BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(form, new object[] { dgv });
}
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);
var dgv = ((MyDataGridView)context.Instance);
var oldSite = dgv.Site;
dgv.Site = ((MyDataGridView)context.Instance).Parent?.Site;
SetLiveDataGridView(dataGridViewColumnCollectionDialog, dgv);
using (var transaction = host.CreateTransaction("DataGridViewColumnCollectionTransaction"))
{
if (service.ShowDialog(dataGridViewColumnCollectionDialog) == DialogResult.OK)
transaction.Commit();
else
transaction.Cancel();
}
dgv.Site = oldSite;
}
return value;
}
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
}
}
构建解决方案。
创建您的 UserControl
并在其上放置一个 MyDataGridView
实例。
公开DataGridView
属性:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public DataGridView DataGridView { get => dataGridView1; }
}
构建解决方案。
将 MyUserControl
的实例拖放到您的表单上,然后在 属性 编辑器 window 中找到 DataGridView
属性,展开它并编辑 Columns
并保存表格。
列现已序列化。给你。
注意: 自定义 UITypeEditor
基于 this post 并进行了一些更改。
结果如下:
private void InitializeComponent()
{
...
...
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.myUserControl1.DataGridView)).BeginInit();
this.SuspendLayout();
//
// myUserControl1
//
//
//
//
this.myUserControl1.DataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.myUserControl1.DataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Column1,
this.Column2});
...
...
//
// Column1
//
this.Column1.HeaderText = "Column1";
this.Column1.MinimumWidth = 6;
this.Column1.Name = "Column1";
this.Column1.Width = 125;
//
// Column2
//
this.Column2.HeaderText = "Column2";
this.Column2.MinimumWidth = 6;
this.Column2.Name = "Column2";
this.Column2.Width = 125;
...
...
((System.ComponentModel.ISupportInitialize)(this.myUserControl1.DataGridView)).EndInit();
this.ResumeLayout(false);
}
...
private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
...
我正在尝试创建一个包含标签、工具条和 Datagridview 的自定义控件。
当测试表单生成设计代码时,它会正确保存工具条项目,但不会保存 Datagridview 列。 代码DGrid.cs
...
[DesignerAttribute(typeof(MultiDesigner))]
public partial class FDGrid : Panel
{
....
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Category("Bars"), Description("Barra dei comandi.")]
public ToolStrip Barra
{
get { return _barra; }
set { _barra = value; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Category("Grid"), Description("Griglia dati.")]
public DataGridView Griglia
{
get { return _griglia; }
set { _griglia = value; }
}
....
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name =
"FullTrust")]
public class MultiDesigner : System.Windows.Forms.Design.ControlDesigner
{
public override void Initialize(IComponent c)
{
base.Initialize(c);
FDGrid ctl = (FDGrid)c;
EnableDesignMode(ctl.Griglia, "Griglia");
EnableDesignMode(ctl.Barra, "Barra");
}
}
...
代码FDGrid.Designer.cs
FDGrid.Designer.cs ....
private FDLabeledImage _titolo;
private ToolStrip _barra;
private DataGridView _griglia;
private void InitializeComponent()
{
this._barra = new System.Windows.Forms.ToolStrip();
this._griglia = new System.Windows.Forms.DataGridView();
this._titolo = new FDControl.FDLabeledImage();
((System.ComponentModel.ISupportInitialize)(this._griglia)).BeginInit();
this.SuspendLayout();
....
((System.ComponentModel.ISupportInitialize)(this._griglia)).EndInit();
this.ResumeLayout(false);
}
.....
代码Form1.Designer.cs
....
private void InitializeComponent()
{
this.fdGrid1 = new FDControl.FDGrid(); // OK
this.fdGrid1.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); **// Error**
this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel(); //OK
}
...
private FDControl.FDGrid fdGrid1; //OK
private System.Windows.Forms.ToolStripLabel toolStripLabel1; //OK
private System.Windows.Forms.DataGridViewTextBoxColumnfdGrid1.Column1;//Error
...
求助,我想明白我哪里错了?
不是最优雅的,但可行的解决方案:
创建自定义
MyDataGridView
派生自DataGridView
:using System; using System.ComponentModel; using System.ComponentModel.Design; using System.Drawing.Design; using System.Reflection; using System.Windows.Forms; using System.Windows.Forms.Design; public class MyDataGridView : DataGridView { [Editor(typeof(ExtendedDataGridViewColumnCollectionEditor), typeof(UITypeEditor))] public new DataGridViewColumnCollection Columns { get => base.Columns; } private 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 ctor = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0]; return (Form)ctor.Invoke(new object[] { provider }); } public static void SetLiveDataGridView(Form form, DataGridView dgv) { var method = form.GetType().GetMethod("SetLiveDataGridView", BindingFlags.NonPublic | BindingFlags.Instance); method.Invoke(form, new object[] { dgv }); } 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); var dgv = ((MyDataGridView)context.Instance); var oldSite = dgv.Site; dgv.Site = ((MyDataGridView)context.Instance).Parent?.Site; SetLiveDataGridView(dataGridViewColumnCollectionDialog, dgv); using (var transaction = host.CreateTransaction("DataGridViewColumnCollectionTransaction")) { if (service.ShowDialog(dataGridViewColumnCollectionDialog) == DialogResult.OK) transaction.Commit(); else transaction.Cancel(); } dgv.Site = oldSite; } return value; } public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } } }
构建解决方案。
创建您的
UserControl
并在其上放置一个MyDataGridView
实例。公开
DataGridView
属性:public partial class MyUserControl : UserControl { public MyUserControl() { InitializeComponent(); } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public DataGridView DataGridView { get => dataGridView1; } }
构建解决方案。
将
MyUserControl
的实例拖放到您的表单上,然后在 属性 编辑器 window 中找到DataGridView
属性,展开它并编辑Columns
并保存表格。
列现已序列化。给你。
注意: 自定义 UITypeEditor
基于 this post 并进行了一些更改。
结果如下:
private void InitializeComponent()
{
...
...
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.myUserControl1.DataGridView)).BeginInit();
this.SuspendLayout();
//
// myUserControl1
//
//
//
//
this.myUserControl1.DataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.myUserControl1.DataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Column1,
this.Column2});
...
...
//
// Column1
//
this.Column1.HeaderText = "Column1";
this.Column1.MinimumWidth = 6;
this.Column1.Name = "Column1";
this.Column1.Width = 125;
//
// Column2
//
this.Column2.HeaderText = "Column2";
this.Column2.MinimumWidth = 6;
this.Column2.Name = "Column2";
this.Column2.Width = 125;
...
...
((System.ComponentModel.ISupportInitialize)(this.myUserControl1.DataGridView)).EndInit();
this.ResumeLayout(false);
}
...
private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
...