Пользовательский Combobox управляет пользовательским источником данных с пользовательским отображаемым элементом и значением. - PullRequest
0 голосов
/ 18 января 2011

Я разрабатываю пользовательский элемент управления списком, который наследуется от другого списка (Янус UICombobox). Мне бы хотелось, чтобы источник данных основывался на EntityType (LLBLGEN), чтобы при выборе EntityType пользователь все записи базы данных для этого EntityType загружались в выпадающий список.

Это нормально, когда я собираю и запускаю, но я также хотел бы иметь возможность дать пользователю возможность выбрать DisplayMember и ValueMember на основе выбранного EntityType.

У меня есть следующий код:

    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 голосов
/ 18 января 2011

Net Framework поддерживает настройку поведения времени разработки несколькими способами. Одним из способов передачи свойств и значений в окно свойств является использование объектов TypeConverter. Возможно, вам удастся заставить это работать, реализовав пользовательский TypeConverter, но это также потребует от вас декорирования всех классов, которые они могут выбрать, и предоставления преобразователей типов для каждого.

Вы можете создать обширный контроль над практически любым аспектом поведения пользовательского элемента управления во время разработки, создав собственный дизайнер. Пользовательский конструктор позволит вам пропустить половинку хака модификаций объектов данных для использования элементом управления UI. Вместо этого вы можете создать свой собственный код для исследования сущностей (например, по Reflection), а затем заполнить окно свойств по своему усмотрению. Создание пользовательских дизайнеров не тривиально и не очень хорошо документировано. Это большая работа, если предположить, что вы не занимаетесь созданием элементов управления для розничного рынка, но нестандартный конструктор - это то, что вам нужно, если вам нужен «профессиональный» элемент управления, который не взломан и работает с любыми объектами данных.

Конечно, это была бы хорошая функция, но, честно говоря, сколько свойств являются даже подходящими кандидатами для этих параметров. У меня почти всегда есть «Id» в качестве элемента значения, а отображаемый элемент обычно имеет порядок «Имя». Выбор (и запоминание) полей для привязки данных имеет тенденцию быть тривиальным, и то, что вы хотите сделать, может оказаться утомительным и трудоемким. Но если вы хотите попробовать ...

Никто не собирается показывать вам, как делать это шаг за шагом, и соответствующие примеры будет трудно найти. Вы в значительной степени сами по себе, когда вы решаетесь на нестандартных дизайнеров. Вот краткий обзор технологии, с которой вы можете начать исследовать методы:

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

0 голосов
/ 18 января 2011

Если у вас есть два свойства (т. Е. Отображаемый элемент и элемент значения), которые пользователь может установить в конструкторе (или в коде), вы сможете вызвать базовый класс (UIComboBox) и установить для них значение их эквивалент в базовом классе.

РЕДАКТИРОВАТЬ (после комментария):

Эта ссылка предоставляет вам 2 способа получения полей сущности данной сущности (один касается модели данных сущности, второй - отражения). Это решает половину вашей проблемы. Но я не знаю, как связать этот список полей с дизайнером ...

...