Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Заполнение ComboBox


Автор: Edd 19.4.2007, 21:35
Создаю свою компоненту (UserControl), у этой компоненты есть свойство,
 которое мозет принимать несколько значений.
Пытаюсь сделать это как ComboBox,
Код

        private ComboBox funkcija=new ComboBox();
        private string[] funk = {"x*x","x*x*x","sin(x)","cos(x)","sqrt(x)" };
        [Browsable(true), DefaultValue(0)]
        public ComboBox MyFunkcija
        {   
            get
            {  return funkcija;  }
            set{
                funkcija.SelectedItem = value.SelectedIndex;
                Paintim();//рисуем
                }
        }
.........

public UserControl1()
        {   
           .......//заполнение
            for (int a = 0; a<5;a++ ) funkcija.Items.Add(funk[a]);
        }

ComboBox у компоненты соответствующий показывается, но он не заполнен.
Как его заполнить?

Автор: Tror 19.4.2007, 22:57
 smile  smile  smile
закидайте меня камнями, но это удаление гланд через хм...... сами знаете что smile

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

вариант #1:
все что нужно это заполнить коллекцию элементов комбобокса в дизайне или в рантайме, в зависимости от потребностей.
Затем в обработчике SelectedValueChanged рисуем то что нам нужно.
Код

private void cbxFunction_SelectedValueChanged(object sender, EventArgs e)
{
    PaintFunc();
}


вариант #2: (это уж если совсем невмоготу и хочется сделать свой компонент)
Наследуем свой класс от комбобокса и переопределяем его метод OnSelectedValueChanged.
Код

    public partial class ComboBoxEx : ComboBox
    {
        public ComboBoxEx()
        {
            InitializeComponent();
        }

        protected override void OnSelectedValueChanged(System.EventArgs e)
        {
            base.OnSelectedValueChanged(e);

            PaintFunc();
        }

        protected virtual void PaintFunc()
        {
            // здесь рисуем в зависимости от выбранного значения в комбобоксе
        }
    }


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

Автор: Kizja 27.11.2009, 15:41
Привет, не хотел новую тему создавать, поэтому решил написать сюда...

Хочу создать свой ComboBox, код следующий:

Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Project {
    class HourComboBox : ComboBox {
        private const int HOURS = 24;

        public HourComboBox() {
            IntegralHeight = false;
            for (int i = 0; i < HOURS; i++) {
                Items.Add(i);
            }
            Console.WriteLine("Size = {0}", Items.Count);
        }
    }
}


В итоге создаёт компонент, но в результате в этом комбобоксе значения выводятся 2 раза - т.е. дубликаты. Такое чувство, что он прогоняет этот цикл 2 раза, но выводит в консоль что элементов как раз 24, сколько и должно быть - что я делаю не так ?

Автор: Exai1e 27.11.2009, 18:30
Цитата(Kizja @  27.11.2009,  15:41 Найти цитируемый пост)
Такое чувство, что он прогоняет этот цикл 2 раза

"Такое чувство" легко откидыватся / подтверждается отладчиком =) бряк на цикл и F10 (вроде) F10 F10 по нужного рез-та
но если выводит нужный рез-тат то все должно быть отлично) да и по коду вроде все норм. Да и вроде не зачем заходить в цикл 2 раза если Вы его не вызываете 2 раза)

Автор: Kizja 28.11.2009, 00:16
Exai1e, походу это какой-то баг в Визуал Студио - мне не поддаётся объяснению такое поведение - попробуйте сами ради интереса, если не очень влом, хотелось бы знать это только у меня так или у всех...

Использую Visual Studio 2008, делаю следующее:

1) Создаю Windows Form приложение
2) Создаю новый класс и добавляю в него тот код, который я привёл выше
3) Компилю, открывается пустая форма, после чего в панеле инструментов появляется этот новый элемент
4) Добавляю его на форму и снова запускаю приложение

В результате в combobox выдаёт 2 раза эти значения:
0
1
2
...
23
0
1
2
...
23

Потом беру и в свойствах этого элемента добавляю вручную в поле Items какие-нибудь значения, теперь уже выводит этот цикл нормально:
0
1
2
...
23
+ дальше те, что ввёл вручную

После этого удаляю те, что ввёл вручную и запускаю снова - теперь выводит список правильно - т.е. 1 раз.

Но если я добавлю на форму второй элемент этого класса, то история повторяется - в первом всё нормально, а в новом опять 2 раза - короче бред какой-то, не пойму...

Попробуйте кто-нибудь пожалуйста и скажите так у вас или нет ?

Автор: Lunatic2009 28.11.2009, 00:51
Только что попробовал, при добавлении этого контрола в файле дизайнера формы появляется следующий код:

Код

this.myComboBox1.Items.AddRange(new object[] {
            0,
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20,
            21,
            22,
            23});

Автор: Kizja 28.11.2009, 02:27
Lunatic2009, спасибо, что попробовал, а при запуске в самом комбобоксе на форме у тебя тоже выводит один цикл ? - потому что у меня в файле дизайнера формы один цикл, но при запуске показывает всё равно два...

вот скриншот с запуска программы: http://pic.ipicture.ru/uploads/091128/2VeW2UnvZ5.jpg

Автор: Lunatic2009 28.11.2009, 02:32
Выводится 2х24, один раз заполняется в конструкторе, второй - в файле дизайнера.

Автор: Kizja 28.11.2009, 11:32
Хм, хорошо, но что я тогда в данной ситуации должен сделать, чтобы показывало бы 1х24 ?- если я уберу этот цикл из конструктора, то вообще нигде не останется этих значений - я так понимаю, что в дизайнере он их генерирует как раз за счёт того цикла, который находится в конструкторе.

Или что невозможно вообще сделать используя наследование комбобокса, чтобы в данной ситуации правильно работало и можно значения задавать только через Items в панеле свойств элемента ?

Может я могу сделать override какому-то методу вместо того чтобы ставить в конструктор этот цикл ?

Извините за возможно тупые вопросы, просто я больше как-то с Java знаком, т.е. в Visual Studio почти ничего не делал раньше.

Автор: Kizja 30.11.2009, 19:01
Ку-ку ? - неужели никто не может ответить ? - это же ненормально, что при запуске программы появляются 2 раза одни и те же значения - неужели те, кто постоянно пользуются Visual Studio не могут ответить в чём может быть дело ? Не верится, что я первый, кто столкнулся с необходимостью наследования комбобокса и добавления в него таким образом значений...

Автор: Exai1e 30.11.2009, 20:46
частично решил через Singleton 
Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public class MyComboBox : ComboBox
    {
        private const int itemCount = 25;
        private static MyComboBox instance;

        public static MyComboBox Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new MyComboBox();
                }
                return instance;
            }
        }

        public MyComboBox()
        {
            if (instance != null)
                for (int curItem = 0; curItem < itemCount; curItem++)
                    Items.Add(curItem);
            //MessageBox.Show(Items.Count.ToString());
        }
        
    }
}

но тогда бред - только 1 компонент... попробую найти еще какое либо решение, вопрос интересный =)
попа какето, в интернете не находил подобных проблем) как то это странно =) нашел точнее, но это видимо ваша, потомучто текст программы один в один)
уфф..  smile 

Автор: Exai1e 30.11.2009, 21:12
кстати, почему то если создавать компонент в рантайме, то все нормально
Код

        private void button1_Click(object sender, EventArgs e)
        {
            MyComboBox mcb = new MyComboBox();
            mcb.Parent = this;
            mcb.Visible = true;
        }

мб и правдо баг VS | компонента ? или визуальные компоненты, что более вероятно (которые потом кидаются с тулбара, пишутся как то иначе....)

Автор: Kizja 30.11.2009, 21:37
Exai1e, только что у меня вроде как получилось сделать по другому - через "пользовательский элемент" (UserControl):

Код

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication3 {
    public partial class HourCombobox : UserControl {
        private const int HOURS = 24;

        public HourCombobox() {
            InitializeComponent();

            comboBox1.IntegralHeight = false;
            for (int i = 0; i < HOURS; i++) {
                comboBox1.Items.Add(i);
            }
        }


        private void HourCombobox_Load(object sender, EventArgs e) {

        }
    }
}


Однако у меня как-то осталось ощущение всё равно, что я не решил проблему, а её обошёл smile

Хотелось бы конечно выяснить, что всё таки с тем вариантом сделать, чтобы заработало, но пока ни от кого внятных ответов не получил...

Автор: Exai1e 30.11.2009, 21:51
Kizja, с тем вариантом "что есть" конструктор Form'ы как уже было написано выше, сам почему то заполняет ComboBox
Код

this.myCB1.Items.AddRange(new object[] {
            0,
            1,
            2,
            3,
            4,
            5,
blablabla});

вопрос, почему ? наверно потому то контролы надо делать через ваше решение, а именно через UserControl
Думаю, проблему вы решили, а не обошли)
Наверно к юзерконтрола есть что то внутри нужное и не известное =) а через WinForms мона делать если только создавать в рантайме.
В написании компонентов не силен вообще, ваш вопрос, дал мне возможность совсем немного "пощупать" это дело =)

Автор: Kizja 30.11.2009, 22:53
Exai1e, просто вопрос тогда в том как вообще правильно писать: например, если мне надо так же наследовать скажем не Combobox, а Checkbox, который будет работать по какому-то моему сценарию, то аналогичного бага как данный скорей всего не возникнет. 

И в таком случае напрашивается простое наследование, чтобы избежать лишние телодвижения, которые возникли с UserControl (добавление самого UserControl компонента + добавление в него Combobox - надобность в которых просто отсутствует).

С другой же стороны использовать всегда обычное наследование и вдруг в каких-то определённых случаях (как например в этом с Combobox) использовать UserControl тоже как-то не очень правильно - нужен какой-то общий принцип и однообразие в этом подходе, а если можно сделать и так и сяк, то ясностью в выборе решения здесь не пахнет smile

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)