2014-09-13 2 views
3

В настоящее время у меня есть ComboBox в моем приложении Windows Forms. Чтобы указать, какие значения будет содержать ComboBox, я устанавливаю свойство DataSource для ComboBox для некоторого массива, чтобы ComboBox содержал значения из этого массива. Я мог бы также использовать Items.Add() для добавления новых значений в ComboBox. Однако я хочу убедиться, что ComboBox может быть заполнен объектами определенного типа. Итак, если у меня есть класс под названием X, то я хочу сделать так, чтобы в качестве источника данных для ComboBox можно было использовать только массив типа X. Сейчас ComboBox принимает объекты типа System.Object. Как я могу это достичь? Есть ли свойство ComboBox, которое мне нужно установить равным имени моего типа данных? Или есть событие, которое проверяет, имеет ли объект, добавленный в мой ComboBox, необходимый тип, и будет ли исключение, если нет?Сделать ComboBox только для определенного типа

Я думал о создании нового класса как подтип ComboBox, и перекрывая Add метод Items собственности таким образом, чтобы добавить проверяет, является ли ее аргумент необходимого типа (не уверен, если и как я могу это сделать). Даже если я это сделаю, есть еще другие способы добавить новые значения в ComboBox (AddRange, CopyTo и т. Д.), Поэтому я думаю, что должно быть более элегантное решение этой проблемы.

+0

Идея, которую вы хотите, возможна, но вы хотите, чтобы кто-то из нас? Попробуйте создать это поле со списком, и после этого напишите, если у вас есть проблемы. – mybirthname

+0

@mybirthname - Нет, я просто хотел узнать, следует ли переопределить метод Add ComboBox.ObjectCollection или, если есть более элегантный способ сделать это, так как технически мне также необходимо переопределить другие методы, которые могут добавлять новые значения в ComboBox, например AddRange. – user3623874

+0

вы не можете скрыть или переопределить 'Items' to * only * принять ваш новый тип, даже если вы наследуете его; но вы можете попробовать обернуть его в UserControl и открыть коллекцию новых элементов. Было бы много кода для эмуляции/имитации существующих свойств и коллекций. Конечно, CBo уже примет ваш конкретный тип, juts not * only *, который Type – Plutonix

ответ

1

Вы можете скрыть Items свойства вашей
собственной Items собственности заказного типа, принимая в качестве параметра оригинального ItemsCollection

Примера класс для тестирования

public class Order 
{ 
    public Int32 ID { get; set; } 
    public string Reference { get; set; } 

    public Order() { } 
    public Order(Int32 inID, string inReference) 
    { 
     this.ID = inID; 
     this.Reference = (inReference == null) ? string.Empty : inReference; 
    } 

    //Very important 
    //Because ComboBox using .ToString method for showing Items in the list 
    public override string ToString() 
    { 
     return this.Reference; 
    } 

} 

С следующим классом я попытался коллекция элементы переноситься ComboBox в собственный тип. Где добавляющие элементы должны быть конкретный тип Здесь вы можете добавить другие методы/свойства, которые нужно (удаление)

public class ComboBoxList<TCustomType> 
{ 
    private System.Windows.Forms.ComboBox.ObjectCollection _baseList; 

    public ComboBoxList(System.Windows.Forms.ComboBox.ObjectCollection baseItems) 
    { 
     _baseList = baseItems; 
    } 

    public TCustomType this[Int32 index] 
    { 
     get { return (TCustomType)_baseList[index]; } 
     set { _baseList[index] = value; } 
    } 

    public void Add(TCustomType item) 
    { 
     _baseList.Add(item); 
    } 

    public Int32 Count { get { return _baseList.Count; } } 

} 

Здесь пользовательский класс выпадающий, полученный из ComboBox Добавлено: общий тип

public class ComboBoxCustomType<TCustomType> : System.Windows.Forms.ComboBox 
{ 
    //Hide base.Items property by our wrapping class 
    public new ComboBoxList<TCustomType> Items; 

    public ComboBoxCustomType() : base() 
    { 
     this.Items = new ComboBoxList<TCustomType>(base.Items); 
    } 

    public new TCustomType SelectedItem 
    { 
     get { return (TCustomType)base.SelectedItem; } 
    } 
} 

Следующая код используемых в форме

private ComboBoxCustomType<Order> _cmbCustom; 

//this method used in constructor of the Form 
private void ComboBoxCustomType_Initialize() 
{ 
    _cmbCustom = new ComboBoxCustomType<Order>(); 
    _cmbCustom.Location = new Point(100, 20); 
    _cmbCustom.Visible = true; 
    _cmbCustom.DropDownStyle = ComboBoxStyle.DropDownList; 
    _cmbCustom.Items.Add(new Order(0, " - nothing - ")); 
    _cmbCustom.Items.Add(new Order(1, "One")); 
    _cmbCustom.Items.Add(new Order(2, "Three")); 
    _cmbCustom.Items.Add(new Order(3, "Four")); 
    _cmbCustom.SelectedIndex = 0; 
    this.Controls.Add(_cmbCustom); 
} 
+0

Да, этот подход работает очень хорошо. Я могу добавить, что ComboBoxList не получен из ComboBox.ObjectCollection, поэтому он не содержит других методов ObjectCollection, таких как AddRange или Remove. Таким образом, для того, чтобы действительно имитировать функциональность ComboBox, нужно было бы реализовать все остальные недостающие методы, как вы реализовали Add(). – user3623874

+0

Вы предложили добавить этот пользовательский ComboBox в форму, выполнив его программно (установив местоположение, видимые свойства и т. Д.). Я не вижу такого рода производного comboBox в панели инструментов для формы, так как он использует generics. Можно ли добавить этот пользовательский comboBox для создания с помощью инструментария вместо того, чтобы делать это программно? – user3623874

+0

Попробуйте изменить ComboBox, используя только ваш тип, а не общий – Fabio

2

Если вы хотите, чтобы контролировать тип элемента, который может содержать ComboBox, вы можете попробовать создать новый класс, производный форму ComboBox, но вы столкнулись с проблемой, что он все еще имеет ComboBox.ObjectCollection Items свойство, которое будет по-прежнему принимать любые тип! И (к сожалению, для вашей идеи переопределения) метод Add не является виртуальным.

Единственное практическое решение, о котором я мог подумать, было бы как-то абстрагировать ComboBox. Если это не общий код, я бы рекомендовал просто создать метод, который вы бы использовали для добавления элементов в ComboBox. Что-то вроде:

// NOTE: All items that are added to comboBox1 need to be of type `SomeType`. 
private void AddItemToComboBox(SomeType item) 
{ 
    comboBox1.Items.Add(item); 
} 

Любой попытки добавить не- SomeType объекта в ComboBox будет удовлетворяться с ошибкой компилятора. К сожалению, нет простого способа помешать кому-то еще добавить пункт SomeType в ComboBox.Items.

Опять же, если это не общий код, это не должно быть проблемой.

+0

Большое спасибо за ваш ответ. Это то, о чем я думал. Я новичок в C#, поэтому я не знаю, будет ли это работать - могу ли я сделать свойство Items моего производного ComboBox частным, чтобы доступ к элементам можно было получить только из метода AddItemToComboBox()? Я не думаю, что это возможно. Еще одна вещь, о которой я думал, - это создать новую (пустую) реализацию метода get для свойства «Items», но использовать исходный метод get свойства Items при добавлении внутри метода AddItemToComboBox().Это возможно? – user3623874

0

Вместо того, чтобы переопределять ComboBox (который не работает, как указано в itsme86's answer), вы можете переопределить usercontrol, добавить к нему комбобокс, а затем только разоблачить элементы, с которыми вы хотите работать. Нечто похожее на

public partial class MyComboBox<T> : UserControl where T: class 
{ 
    public MyComboBox() 
    { 
     InitializeComponent(); 
    } 

    public void Add(T item) 
    { 
     comboBox1.Items.Add(item); 
    } 

    public IEnumerable<T> Items 
    { 
     get { return comboBox1.Items.Cast<T>(); } 
    } 
} 

Пожалуйста, обратите внимание, однако, что некоторые части автоматизированного программного обеспечения полагаться на доступ основные элементы управления, однако, так это может вызвать некоторые проблемы.

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

var myCB = new MyComboBox<ItemClass>(); 
Смежные вопросы