具有自定义displaymember和valuemember的自定义Combobox控件自定义数据源 [英] Custom Combobox control custom datasource with custom displaymember and valuemember

查看:58
本文介绍了具有自定义displaymember和valuemember的自定义Combobox控件自定义数据源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个自定义组合框控件,该控件继承自另一个组合框(Janus UICombobox)。
我希望数据源基于EntityType(LLBLGEN),以便当用户选择EntityType时,该EntityType的所有数据库记录都将加载到组合框中。



在构建和运行时一切正常,但我也希望能够为用户提供基于所选EntityType选择DisplayMember和ValueMember的适当性。



我有以下代码:

 公共局部类DtUiComboBox:UIComboBox 
{
私有线程_loadThread;

public DtUiComboBox()
{
InitializeComponent();
}

//不希望它在设计器中可见
[Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
公共新对象数据源
{
get;
组;
}
//不希望它在设计器中显示
[Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
公共新字符串DisplayMember
{
得到;
组;
}
//不希望它在设计器中显示
[Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
公共新字符串ValueMember
{
得到;
组;
}
//不希望它在设计器中显示
[Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
公共新字符串DataMember
{
得到;
组;
}

//我的自定义DisplayMember应该基于所选EntityType中的EntityField
[Category( Data)]
公共字符串DisplayField
{
得到;
组;
}
//我的自定义ValueMember应该基于所选EntityType中的EntityField
[Category( Data)]
公共字符串ValueField
{
得到;
组;
}

私有EntityType? _entityType;
[Category( Data)]
public EntityType? EntityTypeSource
{
get
{
return _entityType;
}
set
{
if(value!= null)
{
_entityType = value;
IEntity2实体2 = Dal.FactoryClasses.GeneralEntityFactory.Create(_entityType.Value);
if(!DesignMode& ;! ();
_loadThread.Join(500);
}
_loadThread = new Thread(new ThreadStart(LoadFromEntityType));
_loadThread.Start();
}
Invalidate(true);
}
}
}

private void LoadFromEntityType()
{
if(_entityType.HasValue)
{
IEntityCollection2实体集合= DtBlClient.Instance.Bl.GetCollection(_entityType.Value);
LoadFromEntityType(entityCollection);
}
}

私人委托void LoadFromEntityTypeDel(IEntityCollection2 collection2);
private void LoadFromEntityType(object data)
{
if(this.InvokeRequired)
{
this.BeginInvoke(new LoadFromEntityTypeDel(LoadFromEntityType),data);
的回报;
}
DataSource =数据;
}

[BrowsableAttribute(false)]
[Description(此方法检查我是否在DesignMode中运行,因为线程在设计器中不起作用)]
public bool IsDesignerHost
{
get
{
Control ctrl = this;

而(ctrl!= null)
{
if((ctrl.Site!= null)&& ctrl.Site.DesignMode)
返回true ;
ctrl = ctrl.Parent;
}
返回false;
}
}

[Browsable(false)]
[Description(此方法检查我是否在DesignMode中运行,因为线程在Designer中不起作用)]
公共新的静态布尔设计模式
{
get
{
string processName = System.Diagnostics.Process.GetCurrentProcess()。ProcessName;
if(processName.Equals( devenv))
返回true;
返回false;
}
}
}

我该怎么做?

解决方案

Net Framework支持以多种方式自定义设计时行为。将属性和值提供给属性窗口的一种方法是使用TypeConverter对象。您可以通过实现自定义的TypeConverter使其工作,但是它还需要装饰所有可能选择的类,并为每个类提供类型转换器。



您可以通过创建自定义设计器来对自定义控件的设计时行为的几乎所有方面施加广泛的控制。自定义设计器将允许您跳过修改数据实体以供UI控件使用的半招。取而代之的是,您可以构建自己的代码来探索实体(例如,通过反射),然后随心所欲地填充属性窗口。创建自定义设计师并非易事,而且没有充分的文档记录。假设您不从事为零售市场制作控件的工作,这是很多工作,但是如果您想要一个不被黑客入侵并且可以与任何数据实体一起使用的专业控件,那么定制设计师就是您的理想之选。 / p>

当然可以,但是实际上,有多少个属性甚至是这些参数的合适候选者。我几乎总是将 Id作为值成员,而显示成员通常按名称的顺序排列。选择(并记住)用于数据绑定的字段通常很简单,而您想要做的事情可能会变得乏味且耗时。但是,如果您想尝试...



没有人会向您展示如何逐步进行此操作,并且很难找到相关的示例。当您冒险进入定制设计师时,您几乎是一个人。这是该技术的概述文件,可帮助您开始研究这些技术:



http://msdn.microsoft.com/en-us/magazine/cc164048.aspx#S5


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 ?

解决方案

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

这篇关于具有自定义displaymember和valuemember的自定义Combobox控件自定义数据源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆