问题描述
简短说明:
我有一个带有 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.Instance
到 DataGridVeiew
并且由于我们的编辑 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
并编辑 Columns用户控件的私有
DataGridView
字段的 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 属性并通过设计器使其可编辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!