如何在设计时使用 C# WindowsFormApplication 在另一个属性面板上添加现有控件
How to add an existing control in another on properties panel at design time using C# WindowsFormApplication
我有自定义控件:CustomControlOne, CustomControlTwo
。
我的 CustomControlOne
有一个 List<CustomControlTwo>
显示在我的 windows 表单应用程序项目的属性面板中:
因此,当我单击该按钮时,会打开一个 window 以在该集合中添加 新 项:
但是,我想添加在 MyForm 中定义的 existing CustomControlTwo 项。 ps.: MyForm包含CustomControlOne和多个CustomControlTwo。
我希望可以在设计时添加这些项目,就像在组合框中(在 CustomControlOne 属性面板中)选择项目一样。当我将 List<CustomControlTwo>
更改为 ICollection<CustomControlTwo>
时,会显示一个组合框,但不会出现 CustomControlTwo 类型的项目:(
我该怎么做?
我怎么能对我的 CustomControlOne 说 CustomControlTwo 项目在哪里?
谢谢
更新:
我编写了自己的 UITypeEditor,并在@Sefe 和 THIS link 的帮助下实现了我的目标。下面是我的代码:
public class CollectionTypeEditor : UITypeEditor {
private IWindowsFormsEditorService _editorService = null;
private ICollection<Control> mControls = null;
private List<Control> mPickedControls = null;
// Editor like Modal style
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
return UITypeEditorEditStyle.Modal;
}
// Opens modal and get returned data
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
if (provider == null)
return value;
_editorService = (IWindowsFormsEditorService) provider
.GetService(typeof(IWindowsFormsEditorService));
if (_editorService == null)
return value;
mControls = new List<Control>();
// retrieve old data
mPickedControls = value as List<Control>;
if (mPickedControls == null)
mPickedControls = new List<Control>();
// getting existent controls that will be inflated in modal
Control mContext = (Control) context.Instance;
GetControls(mContext);
// open form and get response
CollectionDesign<Control> frmCollections = new CollectionDesign<Control>(mControls, ref mPickedControls);
var response = _editorService.ShowDialog(frmCollections);
// returning data from editor
return response == DialogResult.OK ? mPickedControls : value;
}
这里一切正常。现在,我在属性面板中的变量:
[Editor(typeof(CollectionTypeEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ActionButtonConverter))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<Control> ActionButtons { get; set; }
由于无法保存文件,添加了序列化属性。关闭并重新打开表单时,所有数据都将丢失。
奇怪的是我用 相同的方式 编写了其他 UITypeEditor,只是将数据类型更改为 string
我可以关闭或重新打开我的表单和所有工作正常,数据已保存。
我已经添加了一个 TypeConverter,但我认为这里不是这种情况。我的代码有什么问题?
我的基本设置:
在此设置中,BaseForm
扩展了 Form。字符串有效,但列表数据在关闭表单或构建项目时丢失...
恢复工作流程:
1 - 打开我的表格。
2 - 单击 MyForm 属性面板上的 ActionButtons ellips 是 [...](由 BaseForm 继承)。
3 - 打开一个自定义表单,其中包含我想要挑选的膨胀对象。
4 - 选取我想要的对象并关闭表单。所以现在,数据正常了,因为我可以重新打开该表单并查看我选择的对象。
5 - 现在关闭 MyForm 并重新打开它时,所有数据都丢失了。构建项目时也会发生同样的事情。但是如果我用一个字符串做所有这些steps,一切都很好(数据被保存)。
谢谢大家,抱歉语言不好:P
如果您想向控件中添加多个 CustomControlTwo
项,下拉列表对您没有好处,因为您只能 select 一个值。
如果您能够更改 属性 以接受 CustomControlTwo
的单个实例(或者可以在 属性 浏览器中创建的列表只有一项),您可以创建一个新的 System.ComponentModel.TypeConverter
,它将创建 select 的列表。类型转换器是一个抽象 class 并且您必须实现几个抽象方法。对您有价值的方法是 GetStandardValuesSupported
、GetStandardValuesExclusive
和 GetStandardValues
。这是您感兴趣的部分(您必须添加其他方法):
public class CustomControlOneConverter : TypeConverter {
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
//By returning true, you tell the property designer to add a drop down list
return true;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
//By returning true, you tell the property designer to not allow the user to enter his own text
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
//Get all objects of type CustomControlTwo from the container
CustomControlTwo[] controlsToList =
context.Container.Components.OfType<CustomControlTwo>().ToArray;
//Return a collection of the controls
return new StandardValuesCollection(controlsToList);
}
//implement the other abstract methods
}
你在GetStandardValues
中所做的是在CustomControlOne
的容器中搜索,如果有CustomControlTwo
的实例。然后将这些添加到 属性 浏览器中 select 的标准值列表中。
如果您不能将您的 属性 更改为 select 只有一个 CustomControlTwo
,您将需要创建自己的 UI 在 属性 window 中单击省略号 (...) 时显示。为此,您需要创建自己的 UITypeEditor
。然而,这是一项更复杂的工作,不容易一言以蔽之。
我有自定义控件:CustomControlOne, CustomControlTwo
。
我的 CustomControlOne
有一个 List<CustomControlTwo>
显示在我的 windows 表单应用程序项目的属性面板中:
因此,当我单击该按钮时,会打开一个 window 以在该集合中添加 新 项:
但是,我想添加在 MyForm 中定义的 existing CustomControlTwo 项。 ps.: MyForm包含CustomControlOne和多个CustomControlTwo。
我希望可以在设计时添加这些项目,就像在组合框中(在 CustomControlOne 属性面板中)选择项目一样。当我将 List<CustomControlTwo>
更改为 ICollection<CustomControlTwo>
时,会显示一个组合框,但不会出现 CustomControlTwo 类型的项目:(
我该怎么做? 我怎么能对我的 CustomControlOne 说 CustomControlTwo 项目在哪里? 谢谢
更新:
我编写了自己的 UITypeEditor,并在@Sefe 和 THIS link 的帮助下实现了我的目标。下面是我的代码:
public class CollectionTypeEditor : UITypeEditor {
private IWindowsFormsEditorService _editorService = null;
private ICollection<Control> mControls = null;
private List<Control> mPickedControls = null;
// Editor like Modal style
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
return UITypeEditorEditStyle.Modal;
}
// Opens modal and get returned data
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
if (provider == null)
return value;
_editorService = (IWindowsFormsEditorService) provider
.GetService(typeof(IWindowsFormsEditorService));
if (_editorService == null)
return value;
mControls = new List<Control>();
// retrieve old data
mPickedControls = value as List<Control>;
if (mPickedControls == null)
mPickedControls = new List<Control>();
// getting existent controls that will be inflated in modal
Control mContext = (Control) context.Instance;
GetControls(mContext);
// open form and get response
CollectionDesign<Control> frmCollections = new CollectionDesign<Control>(mControls, ref mPickedControls);
var response = _editorService.ShowDialog(frmCollections);
// returning data from editor
return response == DialogResult.OK ? mPickedControls : value;
}
这里一切正常。现在,我在属性面板中的变量:
[Editor(typeof(CollectionTypeEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ActionButtonConverter))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<Control> ActionButtons { get; set; }
由于无法保存文件,添加了序列化属性。关闭并重新打开表单时,所有数据都将丢失。
奇怪的是我用 相同的方式 编写了其他 UITypeEditor,只是将数据类型更改为 string
我可以关闭或重新打开我的表单和所有工作正常,数据已保存。
我已经添加了一个 TypeConverter,但我认为这里不是这种情况。我的代码有什么问题?
我的基本设置:
在此设置中,BaseForm
扩展了 Form。字符串有效,但列表数据在关闭表单或构建项目时丢失...
恢复工作流程:
1 - 打开我的表格。
2 - 单击 MyForm 属性面板上的 ActionButtons ellips 是 [...](由 BaseForm 继承)。
3 - 打开一个自定义表单,其中包含我想要挑选的膨胀对象。
4 - 选取我想要的对象并关闭表单。所以现在,数据正常了,因为我可以重新打开该表单并查看我选择的对象。
5 - 现在关闭 MyForm 并重新打开它时,所有数据都丢失了。构建项目时也会发生同样的事情。但是如果我用一个字符串做所有这些steps,一切都很好(数据被保存)。
谢谢大家,抱歉语言不好:P
如果您想向控件中添加多个 CustomControlTwo
项,下拉列表对您没有好处,因为您只能 select 一个值。
如果您能够更改 属性 以接受 CustomControlTwo
的单个实例(或者可以在 属性 浏览器中创建的列表只有一项),您可以创建一个新的 System.ComponentModel.TypeConverter
,它将创建 select 的列表。类型转换器是一个抽象 class 并且您必须实现几个抽象方法。对您有价值的方法是 GetStandardValuesSupported
、GetStandardValuesExclusive
和 GetStandardValues
。这是您感兴趣的部分(您必须添加其他方法):
public class CustomControlOneConverter : TypeConverter {
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
//By returning true, you tell the property designer to add a drop down list
return true;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
//By returning true, you tell the property designer to not allow the user to enter his own text
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
//Get all objects of type CustomControlTwo from the container
CustomControlTwo[] controlsToList =
context.Container.Components.OfType<CustomControlTwo>().ToArray;
//Return a collection of the controls
return new StandardValuesCollection(controlsToList);
}
//implement the other abstract methods
}
你在GetStandardValues
中所做的是在CustomControlOne
的容器中搜索,如果有CustomControlTwo
的实例。然后将这些添加到 属性 浏览器中 select 的标准值列表中。
如果您不能将您的 属性 更改为 select 只有一个 CustomControlTwo
,您将需要创建自己的 UI 在 属性 window 中单击省略号 (...) 时显示。为此,您需要创建自己的 UITypeEditor
。然而,这是一项更复杂的工作,不容易一言以蔽之。