這是一個遲到的答案,但如果你仍然感興趣,這裏是如何做到這一點。
對於您的StringManager和您的ComponentReader類都有相當多的要求。
1)這兩個類都需要從System.ComponentModel.Component派生。
2)StringManager必須重寫Component類的Site屬性。這就是「VS Designer意識到」的原因,並且可以在稍後的ComponentReader屬性中進行選擇。
3)StringManager必須公開List作爲公共屬性。爲了方便起見,在我的示例代碼bolow中,我已經在VS屬性網格中設置了EditorAttribute以實現簡單的字符串集合版本。
4)ComponentReader必須實現一個只有一個StringManager類型屬性的自定義接口。這是需求#6所需要的。
5)ComponentReader必須具有ComponentReader必須具有類型字符串的SelectedString的公共屬性類型StringManager
6)的公共屬性。我們必須將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 Forms項目,將這些文件添加到它,並生成項目。
現在,在您的窗體上,您可以通過從工具箱中拖動來添加每個StringManager和ComponentReader的實例。
選擇StringManager,並在屬性中使用字符串集合編輯器向TheList添加一些字符串。
選擇ComponentReader,並在屬性窗口中,您應該能夠從下拉列表中選擇您的StringManager實例。
您現在應該可以從SelectedString的下拉列表中選擇一個字符串。
我希望你喜歡
呂克
也許你應該備份,並解釋你提出的「解決方案」是爲了解決問題。這可能是另一種解決原始問題的方法。 – Tergiver 2011-04-22 15:26:45
我只想學習如果我可以做到這一點...以及如何做到這一點,也許不止一個解決方案... – guillaume 2011-04-22 21:26:27