Har*_*lse 6 c# user-controls datagridview windows-forms-designer winforms
简短的介绍:
我有一个带有DataGridView的UserControl。我想向设计者公开DataGridView Columns集合,因此我可以在设计时更改用户控件上的列。
问:为此,我需要哪些设计师属性?
对于那些对较长版本感兴趣的人:
我有一个具有以下功能的UserControl:
该用户控件可以自主运行。它具有父控件要使用的一个功能:
UserControl引发两个事件:
我必须以几种形式显示此用户控件。唯一的区别是每个表格的DataGridViewColumn集合不同。
我可以以编程方式添加列,但是使用设计器创建列会更容易。
通常,注册一个合适的UITypeEditorusing [Editor]属性就足够了。它使用的编辑器DataGridView是DataGridViewColumnCollectionEditor。但是在这种情况下,如果我们直接使用此编辑器,则该编辑器期望该属性属于a DataGridView并尝试将to的值转换为ITypeDescriptorContext.Instance,DataGridVeiew并且由于我们的editing Columns属性属于我们的用户控件,因此我们将收到异常:
无法将类型为'的对象强制转换
Type of Control'为'System.Windows.Forms.DataGridView'。
为了解决该问题,我们需要创建一个自定义UITypeEditor以及覆盖EditValue和编辑用户控件Columns私有DataGridView字段的属性。
为此,我们创建一个ITypeDescriptorContext包含DataGridView和Columns属性的实例,并将其传递给EditValue编辑器的方法。这样,编辑器将编辑我们的Columns属性。
我们还使用[DesignerSerializationVisibility]属性修饰属性以序列化集合内容。
这是实现。
MyUserControl
我想您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; }
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
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;
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)