如何在设计时使用 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 并且您必须实现几个抽象方法。对您有价值的方法是 GetStandardValuesSupportedGetStandardValuesExclusiveGetStandardValues。这是您感兴趣的部分(您必须添加其他方法):

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。然而,这是一项更复杂的工作,不容易一言以蔽之。