C # Почему невозможно установить selectedValue динамически созданного комбинированного списка? - PullRequest
4 голосов
/ 08 июля 2010

Я создаю комбинированный список в классе и хочу установить выбранное значение для этого комбинированного списка.Но когда я делаю это, selectedValue остается нулевым, и когда я пытаюсь установить selectedIndex, я получаю ArgumentOutOfRangeException.

Код:

public Control GenerateList(Question question)
{
    // Clear the local givenAnswer collection
    _givenAnswer.Clear();

    // Get a list with answer possibilities
    List<QuestionAnswer> answers = question.GetAnswerSort();

    // Get a collection of given answers
    Collection<QuestionnaireAnswer> givenAnswers = question.GetGivenAnswers();

    _givenAnswer = givenAnswers;

    ComboBox cmb = new ComboBox();
    cmb.Name = "cmb";
    cmb.DisplayMember = "Answer";
    cmb.ValueMember = "Id";
    cmb.DataSource = answers;
    cmb.Dock = DockStyle.Top;

    // Check an answer is given to the question
    if (givenAnswers != null && givenAnswers.Count > 0)
    {
        cmb.Tag = givenAnswers[0].AnswerId;
        cmb.SelectedValue = givenAnswers[0].AnswerId; // answerId = 55, but SelectedValue stays null
    }

    cmb.SelectedIndex = 1; // For testting. This will throw a ArgumentOutOfRangeException
    cmb.DropDownStyle = ComboBoxStyle.DropDownList;
    cmb.SelectedIndexChanged += new EventHandler(cmb_SelectedIndexChanged);

    return cmb;
}

Я надеюсь, что кто-то может объяснить мне, что происходит, и я могу понять, почему это не работает.

Вот небольшая полная программачто иллюстрирует мою проблему.Как вы можете видеть, он не устанавливает SelectedValue, он остается нулевым

namespace Dynamic_Create_Combo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            GenerateControls gc = new GenerateControls();
            Control c = gc.GenerateCombo();

            this.SuspendLayout();
            this.Controls.Add(c);
            this.ResumeLayout(true);
        }
    }

    public class GenerateControls
    {
        public Control GenerateCombo()
        {
            // Create datasource
            Collection<Car> cars = new Collection<Car>();
            Car c = new Car();
            c.Id = 1;
            c.Name = "Car one";
            cars.Add(c);

            Car c1 = new Car();
            c1.Id = 2;
            c1.Name = "Car two";
            cars.Add(c1);

            Car c2 = new Car();
            c2.Id = 2;
            c2.Name = "Car three";
            cars.Add(c2);

            ComboBox cmb = new ComboBox();
            cmb.DropDownStyle = ComboBoxStyle.DropDownList;
            cmb.DataSource = cars;
            cmb.DisplayMember = "Name";
            cmb.ValueMember = "Id";

            cmb.SelectedValue = 2;

            return cmb;
        }
    }

    public class Car
    {
        private int _id;
        private string _name;

        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public string Name 
        {
            get { return _name; }
            set { _name = value; }
        }
    }
}

Ответы [ 5 ]

10 голосов
/ 08 июля 2010

Вы установили значение элемента «Id», но пытаетесь использовать «AnswerId» в качестве выбранного значения.

Без подробностей трудно сказать, почему настройка SelectedIndexвыдает ArgumentOutOfRangeException - возможно, поле со списком игнорирует все значения, которые не имеют свойства "Id", что не дает никаких значений, поэтому выбор индекса 1 невозможен?

РЕДАКТИРОВАТЬ: Хорошо, так выглядиткак будто он выполняет связывание, только когда оно становится видимым - или на каком-то этапе процесса.Я пробовал несколько вещей, чтобы ускорить это, но они не помогают.То, что вы можете сделать, это отложить ваш выбор:

EventHandler visibleChangedHandler = null;
visibleChangedHandler = delegate {
    cmb.SelectedIndex = 2;
    cmb.VisibleChanged -= visibleChangedHandler; // Only do this once!
};
cmb.VisibleChanged += visibleChangedHandler;

Это уродливый обходной путь, но он должен, по крайней мере, помочь вам начать работу на данный момент.

3 голосов
/ 08 июля 2010

Это всего лишь предположение, но, возможно, ComboBox не связывает данные в DataSource, пока они не будут нарисованы.Проверьте cmb.Items.Count в строке перед SelectedIndex = 1.Если это 0, попробуйте сначала добавить cmb к Form, прежде чем присваивать SelectedIndex.

EDIT:

    public Control GenerateCombo() 
    { 
        // Create datasource 
        Collection<Car> cars = new Collection<Car>(); 
        Car c = new Car(); 
        c.Id = 1; 
        c.Name = "Car one"; 
        cars.Add(c); 

        Car c1 = new Car(); 
        c1.Id = 2; 
        c1.Name = "Car two"; 
        cars.Add(c1); 

        Car c2 = new Car(); 
        c2.Id = 2; 
        c2.Name = "Car three"; 
        cars.Add(c2); 

        ComboBox cmb = new ComboBox(); 
        cmb.DropDownStyle = ComboBoxStyle.DropDownList; 
        cmb.DataSource = cars; 
        cmb.DisplayMember = "Name"; 
        cmb.ValueMember = "Id"; 

        // add this: 
        EventHandler visibleChangedHandler = null; 
        visibleChangedHandler = delegate { 
            cmb.SelectedIndex = 2; 
            cmb.VisibleChanged -= visibleChangedHandler;
        }; 
        cmb.VisibleChanged += visibleChangedHandler; 

        // delete this: cmb.SelectedValue = 2; 

        return cmb; 
    } 
1 голос
/ 14 марта 2016

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

public class Form1
{


private ComboBox _comboBox1;
private Car _audi = new Car("Audi)");
private Car _porsche = new Car("Porsche");
private Car _vw = new Car("VW");

private void Form1_Load(object sender, EventArgs e)
{
    this._comboBox1.SelectedItem = _vw;

}


public Form1()
{
    Load += Form1_Load;
    // This call is required by the designer.
    InitializeComponent();

    // Add any initialization after the InitializeComponent() call.
    this._comboBox1 = new ComboBox();
    this._comboBox1.DataSource = {
        _audi,
        _porsche,
        _vw
    };
    this.Controls.Add(this._comboBox1);
}



private class Car
{

    public string Name { get; set; }

    public override string ToString()
    {
        return this.Name;

    }

    public Car(name)
    {
        this.Name = name;
    }
}

}
1 голос
/ 08 июля 2010

Вам нужно установить cmb.DataBindings и , это может помочь.

0 голосов
/ 08 июля 2010

Возможно, вы захотите попробовать SelectedItem вместо SelectedValue и назначить класс, который вам нужен.Например:

Car c1 = new Car();
// snip
cmb.SelectedItem = c1;

Поскольку более чем один элемент может иметь значение 2 (насколько известно ComboBox, в любом случае), я думаю, у вас возникнут трудности настройка значение через SelectedValue.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...