我正在开发一个自定义组合框控件,它继承自另一个组合框(Janus UICombobox)。 我希望数据源基于EntityType(LLBLGEN),这样当用户选择EntityType时,该EntityType的所有数据库记录都将加载到组合框中。
当我构建和运行时,这很好,但我也希望能够为用户提供基于所选EntityType选择DisplayMember和ValueMember的机会。
我有以下代码:
public partial class DtUiComboBox : UIComboBox
{
private Thread _loadThread;
public DtUiComboBox()
{
InitializeComponent();
}
//Don't want this to be visible in the designer
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new object DataSource
{
get;
set;
}
//Don't want this to be visible in the designer
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new string DisplayMember
{
get;
set;
}
//Don't want this to be visible in the designer
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new string ValueMember
{
get;
set;
}
//Don't want this to be visible in the designer
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new string DataMember
{
get;
set;
}
//My Custom DisplayMember that should be based on the EntityFields from the selected EntityType
[Category("Data")]
public string DisplayField
{
get;
set;
}
//My Custom ValueMember that should be based on the EntityFields from the selected EntityType
[Category("Data")]
public string ValueField
{
get;
set;
}
private EntityType? _entityType;
[Category("Data")]
public EntityType? EntityTypeSource
{
get
{
return _entityType;
}
set
{
if (value != null)
{
_entityType = value;
IEntity2 entity2 = Dal.FactoryClasses.GeneralEntityFactory.Create(_entityType.Value);
if (!DesignMode && !IsDesignerHost)
{
if (_loadThread != null && _loadThread.IsAlive)
{
_loadThread.Abort();
_loadThread.Join(500);
}
_loadThread = new Thread(new ThreadStart(LoadFromEntityType));
_loadThread.Start();
}
Invalidate(true);
}
}
}
private void LoadFromEntityType()
{
if (_entityType.HasValue)
{
IEntityCollection2 entityCollection = DtBlClient.Instance.Bl.GetCollection(_entityType.Value);
LoadFromEntityType(entityCollection);
}
}
private delegate void LoadFromEntityTypeDel(IEntityCollection2 collection2);
private void LoadFromEntityType(object data)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new LoadFromEntityTypeDel(LoadFromEntityType), data);
return;
}
DataSource = data;
}
[BrowsableAttribute(false)]
[Description("This method checks if I run in DesignMode, because Threading doesn't work in the Designer")]
public bool IsDesignerHost
{
get
{
Control ctrl = this;
while (ctrl != null)
{
if ((ctrl.Site != null) && ctrl.Site.DesignMode)
return true;
ctrl = ctrl.Parent;
}
return false;
}
}
[Browsable(false)]
[Description("This method checks if I run in DesignMode, because Threading doesn't work in the Designer")]
public new static bool DesignMode
{
get
{
string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
if (processName.Equals("devenv"))
return true;
return false;
}
}
}
我该怎么做?
答案 0 :(得分:0)
如果您有两个属性(即显示成员和值成员),用户可以在设计器中(或在代码中)设置,您应该能够调用基类(UIComboBox
)并设置这些属性值等于基类中的等价物。
This link为您提供了两种获取给定实体的实体字段的方法(一种处理实体数据模型,第二种处理反射)。它解决了你的一半问题。但我不知道将这个字段列表绑定到设计器的方法......
答案 1 :(得分:0)
Net Framework支持以多种方式自定义设计时行为。将属性和值提供给属性窗口的一种方法是使用TypeConverter对象。您可以通过实现自定义TypeConverter来实现此功能,但它还需要您装饰他们可能选择的所有类,并为每个类提供类型转换器。
通过创建自定义设计器,您可以对自定义控件的设计时间行为的任何方面进行广泛控制。自定义设计器允许您跳过修改数据实体以供UI控件使用的半黑客。相反,您可以构建自己的代码来探索实体(例如反射),然后填充属性窗口,无论您选择什么。创建自定义设计器并非易事,而且没有详细记录。这是一项很多工作,假设您不是为零售市场制作控制权,但如果您想要一个没有被黑客攻击并且可以与任何数据实体合作的“专业”控件,那么定制设计师就是您的选择。 / p>
当然这将是一个很好的功能,但老实说,有多少属性甚至适合这些参数。我几乎总是将“Id”作为值成员,并且显示成员通常是“名称”的顺序。选择(和记住)数据绑定的字段往往是微不足道的,你想做的事情可能会变得乏味和耗时。但如果你想尝试......
没有人会告诉你如何一步一步地做这件事,相关的例子很难找到。冒险进入定制设计师时,你几乎可以自己独立。以下是开始研究技术的技术概述: