我希望有一个“表单”或者其他什么东西(不管是什么),可以将字符串添加到列表中。
它将使用包含字符串集合的第一个组件"StringManager“来完成。
另一方面,我希望有另一个组件"ComponentReader“使用IExtenderProvider,并在所有控件(组件窗体上)上添加一个名为"TheString”的属性,该属性允许我从列表中选择一个字符串
因此,为了清楚起见:我希望共享每个表单上的代码最少的List<String> (大多数使用属性编辑器)。
我不知道我怎么能告诉"ComponentReader“他所指的主要成分在哪里,
(我在我的“ReferedStringManager”中添加了一个属性ComponentReader)。
是否有任何属性或指令(或方式)来检查项目和他的引用以获得ComponentReader的ReferedStringManager属性的"ComponentReader“属性中所有可匹配的值;
如果不可能,我会想到静态列表或其他东西,可能是XML文件(但我不知道如何在构思期间管理它)
当然,所有这些都是在设计时,而不是在执行时(这将是如此简单!)
发布于 2011-08-15 01:23:26
这是一个迟来的答案,但如果你仍然感兴趣,下面是如何做到这一点。
StringManager和ComponentReader类都有相当多的需求。
1)这两个类都需要从System.ComponentModel.Component派生。
2) StringManager必须覆盖组件类的Site属性。这就是让它"VS Designer感知“的原因,并允许以后在ComponentReader的属性中选择它。
3) StringManager必须将列表公开为公共属性。为了方便起见,在我的示例代码bolow中,我在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,并在属性中使用string集合编辑器向TheList添加几个字符串。
选择ComponentReader,在属性窗口中,您应该能够从下拉列表中选择StringManager实例。
现在,您应该能够从SelectedString的下拉列表中选择一个字符串。
我希望你喜欢
Luc
https://stackoverflow.com/questions/5754589
复制相似问题