这是一个迟到的答案,但如果你仍然感兴趣,这里是如何做到的。
StringManager 和 ComponentReader 类都有很多要求。
1) 两个类都需要派生自 System.ComponentModel.Component。
2) StringManager 必须覆盖 Component 类的 Site 属性。这就是让它“感知 VS 设计器”的原因,并允许稍后在 ComponentReader 的属性中选择它。
3) StringManager 必须将 List 公开为公共属性。为方便起见,在下面的示例代码中,我在 VS 属性网格中设置了 EditorAttribute 用于简单的字符串集合版本。
4) ComponentReader 必须实现一个自定义接口,该接口只有一个 StringManager 类型的属性。这是第 6 条要求所需要的。
5) ComponentReader 必须具有 StringManager 类型的公共属性
6) ComponentReader 必须具有用于 SelectedString 的字符串类型的公共属性。问题是我们必须将 TypeConverterAttribute 设置为另一个我们必须实现的类(参见 #7)
7) 我们必须实现一个 StringConverter 派生类。这将用于允许我们从选定的 StringManager 中选择一个字符串。在这个类中,我们必须能够通过 #4 中创建的接口检索对 ComponentReader 的引用。
现在,代码:
StringManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.ComponentModel.Design;
namespace VSDesignHost
{
class StringManager : Component
{
private ContainerControl _containerControl = null;
public StringManager()
{
TheList = new List<string>();
}
public StringManager(IContainer container) : this()
{
container.Add(this);
InitializeComponent();
}
private void InitializeComponent()
{
//Whatever
}
public ContainerControl ContainerControl
{
get { return _containerControl; }
set { _containerControl = value; }
}
public override ISite Site
{
set
{
base.Site = value;
if (value != null)
{
IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host != null)
{
IComponent rootComponent = host.RootComponent;
if (rootComponent is ContainerControl)
{
this.ContainerControl = (ContainerControl)rootComponent;
}
}
}
}
}
[Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design", "System.Drawing.Design.UITypeEditor, System.Drawing")]
public List<string> TheList { get; set; }
}
}
ComponentReader.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace VSDesignHost
{
class ComponentReader : Component, IStringManagerEnabled
{
private StringManager sm;
public ComponentReader()
{
sm = null;
}
[Browsable(true), Category("MyCategory")]
public StringManager StringManager
{
get { return sm; }
set
{
sm = value;
}
}
[Browsable(true), Category("MyCategory"), TypeConverter(typeof(StringManagerStringConverter))]
public string SelectedString { get; set; }
}
}
IStringManagerEnabled.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VSDesignHost
{
interface IStringManagerEnabled
{
StringManager StringManager
{
get;
set;
}
}
}
StringManagerStringConverter.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace VSDesignHost
{
class StringManagerStringConverter : StringConverter
{
#region Make It A ComboBox
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return false;
}
#endregion
#region Display Tags In List
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
if ((context == null) || (context.Container == null))
{
return null;
}
Object[] Tags = this.GetTagsFromServer(context);
if (Tags != null)
{
return new StandardValuesCollection(Tags);
}
return null;
}
private object[] GetTagsFromServer(ITypeDescriptorContext context)
{
List<string> availableTags = new List<string>();
if (context.Instance == null)
{
availableTags.Add("ITypeDescriptorContext.Instance is null");
return availableTags.ToArray();
}
IStringManagerEnabled inst = context.Instance as IStringManagerEnabled;
if (inst == null)
{
availableTags.Add(context.Instance.ToString());
return availableTags.ToArray();
}
if (inst.StringManager == null)
{
availableTags.Add("No StringManager selected");
return availableTags.ToArray();
}
availableTags = inst.StringManager.TheList;
availableTags.Sort(Comparer<string>.Default);
return availableTags.ToArray();
}
#endregion
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string)
return value.ToString();
return base.ConvertFrom(context, culture, value);
}
}
}
创建一个 Windows 窗体项目,将这些文件添加到其中,然后构建项目。
现在,在您的表单上,您可以通过从工具箱中拖动来添加每个 StringManager 和 ComponentReader 的实例。
选择StringManager,并在属性中,使用字符串集合编辑器将一些字符串添加到TheList。
选择 ComponentReader,然后在属性窗口中,您应该能够从下拉列表中选择您的 StringManager 实例。
您现在应该能够从 SelectedString 的下拉列表中选择一个字符串。
希望你喜欢
卢克