自定义Combobox控件自定义数据源与自定义显示成员和值成员

时间:2011-01-18 10:51:48

标签: c# winforms combobox custom-controls

我正在开发一个自定义组合框控件,它继承自另一个组合框(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;
        }
    }
}

我该怎么做?

2 个答案:

答案 0 :(得分:0)

如果您有两个属性(即显示成员和值成员),用户可以在设计器中(或在代码中)设置,您应该能够调用基类(UIComboBox)并设置这些属性值等于基类中的等价物。

编辑(评论后):

This link为您提供了两种获取给定实体的实体字段的方法(一种处理实体数据模型,第二种处理反射)。它解决了你的一半问题。但我不知道将这个字段列表绑定到设计器的方法......

答案 1 :(得分:0)

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

通过创建自定义设计器,您可以对自定义控件的设计时间行为的任何方面进行广泛控制。自定义设计器允许您跳过修改数据实体以供UI控件使用的半黑客。相反,您可以构建自己的代码来探索实体(例如反射),然后填充属性窗口,无论您选择什么。创建自定义设计器并非易事,而且没有详细记录。这是一项很多工作,假设您不是为零售市场制作控制权,但如果您想要一个没有被黑客攻击并且可以与任何数据实体合作的“专业”控件,那么定制设计师就是您的选择。 / p>

当然这将是一个很好的功能,但老实说,有多少属性甚至适合这些参数。我几乎总是将“Id”作为值成员,并且显示成员通常是“名称”的顺序。选择(和记住)数据绑定的字段往往是微不足道的,你想做的事情可能会变得乏味和耗时。但如果你想尝试......

没有人会告诉你如何一步一步地做这件事,相关的例子很难找到。冒险进入定制设计师时,你几乎可以自己独立。以下是开始研究技术的技术概述:

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