问题
I'm developing a custom combobox control that inherits from another combobox (Janus UICombobox). I'd like the datasource to be based on a EntityType (LLBLGEN) so that when a user selects a EntityType all the database records for that EntityType will be loaded in the combobox.
This is going fine when I build and run, but I would also like to be able to give the user the apportunity to select the DisplayMember and ValueMember based on the selected EntityType.
I have the following code:
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;
}
}
}
How can I do this ?
回答1:
If you have two properties (i.e. display member and value member) which the user can set in the designer (or in the code), you should be able to call your base class (UIComboBox
) and set those value to their equivalent in the base class.
EDIT (after comment):
This link provides you 2 ways of getting the entity fields of a given entity (one dealing with Entity Data Model, the second with Reflection). It solves half of your problem. But I don't know a way to bind this list of fields to the designer...
回答2:
Net Framework supports customizing design time behavior in several ways. One way to feed properties and values to the property window is by TypeConverter objects. You may be able to get this to work by implementing a custom TypeConverter, but it would also require you to decorate all the classes they could possibly select and provide type converters for each.
You can exert extensive control over just about any aspect of design time behavior of a custom control by creating a custom designer. A custom designer would allow you to skip the semi-hack of modifying data entities for use by a UI control. Instead you could build your own code to explore entities (ex. by Reflection) and then populate the property window however you choose. Creating custom designers is not trivial, and it is not well documented. This is a lot of work assuming you are not in the business of making controls for the retail market, but a custom designer is the way to go if you want a "professional" control that is not hacked and works with any data entities.
Sure it would be a nice feature, but honestly, how many properties are even suitable candidates for these parameters. I almost invariably have "Id" as a value member and display member is typically something on the order of "Name". Selecting (and remembering) fields for databinding tends to be trivial, and what you want to do could prove tedious and time consuming. But if you want to try...
No one is going to show you how to do this step by step, and the relevant examples will be hard to find. You are pretty much on your own when you venture into custom designers. Here is an overview paper of the technology to get you started on researching the techniques:
http://msdn.microsoft.com/en-us/magazine/cc164048.aspx#S5
来源:https://stackoverflow.com/questions/4723207/custom-combobox-control-custom-datasource-with-custom-displaymember-and-valuemem