отсортированное поле со списком и переназначение источника данных

Общие сведения. Есть два поля со списком, которые отличаются только свойством "Сортировка". Для comboBox1 для свойства Sorted задано значение true, а для comboBox2 для свойства Sorted установлено значение false. При попытке переназначить/сбросить свойство источника данных этих двух полей со списком, comboBox1 не отображает данные, а comboBox2 показывает. Почему свойство Sorted не позволяет comboBox1 правильно отображать свои данные?

Весь код включен ниже:

public partial class Form1 : Form
{
    private string[] a8BitGames = { "Metroid", "Zelda", "Phantasy Star", "SB:S&SEP" };
    private string[] a16BitGames = { "StarFox", "Link", "Final Fantasy", "Altered Beast" };
    private List<string> lSomeList = null;
    private List<string> lSomeOtherList = null;

    public Form1()
    {
        InitializeComponent();
        this.lSomeList = new List<string>(a8BitGames);
        this.lSomeOtherList = new List<string>(a16BitGames);
        this.comboBox1.DataSource = lSomeList;
        this.comboBox2.DataSource = lSomeOtherList;
    }

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        this.IndexChanged(1);
    }

    private void IndexChanged(int comboBox)
    {
        this.comboBox1.DataSource = null;
        this.comboBox1.DataSource = a16BitGames;

        this.comboBox2.DataSource = null;
        this.comboBox2.DataSource = a8BitGames;
    }

    private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
    {
        this.IndexChanged(2);
    }
}

partial class Form1
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.comboBox1 = new System.Windows.Forms.ComboBox();
        this.comboBox2 = new System.Windows.Forms.ComboBox();
        this.SuspendLayout();
        // 
        // comboBox1
        // 
        this.comboBox1.FormattingEnabled = true;
        this.comboBox1.Location = new System.Drawing.Point(13, 13);
        this.comboBox1.Name = "comboBox1";
        this.comboBox1.Size = new System.Drawing.Size(121, 21);
        this.comboBox1.Sorted = true;
        this.comboBox1.TabIndex = 0;
        this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
        // 
        // comboBox2
        // 
        this.comboBox2.FormattingEnabled = true;
        this.comboBox2.Location = new System.Drawing.Point(13, 41);
        this.comboBox2.Name = "comboBox2";
        this.comboBox2.Size = new System.Drawing.Size(121, 21);
        this.comboBox2.TabIndex = 1;
        this.comboBox2.SelectedIndexChanged += new System.EventHandler(this.comboBox2_SelectedIndexChanged);
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(284, 262);
        this.Controls.Add(this.comboBox2);
        this.Controls.Add(this.comboBox1);
        this.Name = "Form1";
        this.Text = "Form1";
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.ComboBox comboBox1;
    private System.Windows.Forms.ComboBox comboBox2;
}

person HighExodus    schedule 29.07.2013    source источник
comment
Почему вы хотите переназначить источник данных в измененном индексе?   -  person Sriram Sakthivel    schedule 30.07.2013
comment
@Sriram, это пример кода. В реальной программе я управляю общим набором значений в нескольких полях со списком, и никакие два поля со списком не могут выбрать одно и то же значение. Всякий раз, когда индекс изменяется, я удаляю новый индексированный элемент из списка и добавляю старый. Таким образом, новый индексированный элемент удаляется как выбор из других полей со списком, а старый индексируемый элемент добавляется как выбор. Хотя не уверен, что это относится к вопросу...   -  person HighExodus    schedule 30.07.2013


Ответы (3)


Вы случайно не скрываете исключение? Согласно MSDN, вы получите «ArgumentException», когда «была предпринята попытка отсортировать ComboBox, прикрепленный к источнику данных».

http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.sorted.aspx

person Paul Zaczkowski    schedule 29.07.2013
comment
Я согласен, но нет, я не скрываю исключения, я никогда не получаю его. Интересно, если свойство по умолчанию имеет значение true, как-то предотвращает возникновение исключения... - person HighExodus; 30.07.2013
comment
Это скрывает исключение, потому что, когда вы пытаетесь установить comboBox1.Sorted = false, а затем вернуться к true, возникает ошибка: ComboBox с набором DataSource не может быть отсортирован. Отсортируйте данные, используя базовую модель данных. - person Martijn van Put; 30.07.2013
comment
HighExodus не столько по умолчанию, сколько тот факт, что когда вы устанавливаете sorted, элемент не является элементом управления с привязкой к данным (пока). Попробуйте установить this.comboBox1.Sorted = true; в конце вашего метода IndexChanged(...), и я уверен, вы увидите исключение. - person Paul Zaczkowski; 30.07.2013
comment
@PaulZaczkowski, я следую вашим рассуждениям (и согласен с ними), но почему первоначальное назначение источника данных работает так, как ожидалось? - person HighExodus; 30.07.2013
comment
HighExodus Я не уверен, что вы наткнулись на ошибку, или мы оба что-то упустили. Казалось бы, вы не можете изменить DataSource отсортированного ComboBox после начальной загрузки. Кроме того, отсутствие исключений здесь действительно очень странно. Может быть, у кого-то есть более глубокое понимание :/ - person Paul Zaczkowski; 30.07.2013
comment
@PaulZaczkowski, спасибо за вклад! Что-то мне подсказывает, что это особенность .NET. К сожалению для меня, потребовалось довольно много времени, чтобы понять, что происходит... - person HighExodus; 30.07.2013

Попробуйте отсортировать, отсортировав список при настройке DataSource

 public List<string> A16Games
 {
    get { return this.a16BitGames.OrderBy(x => x).ToList(); }
 }

 public List<string> A8Games
 {
    get { return this.a8BitGames.OrderBy(x => x).ToList(); }
 }

 this.comboBox1.DataSource = this.A16Games;
 this.comboBox2.DataSource = this.A8Games;
person Martijn van Put    schedule 29.07.2013
comment
@Martjin van Put, спасибо, Мартин. Это допустимый подход, который можно использовать для сортировки списка, отображаемого в поле со списком; однако меня больше интересовало, почему .NET позволяет корректно работать (отсортировать) начальное назначение источника данных для comboBox1, но все остальные попытки терпят неудачу. - person HighExodus; 30.07.2013
comment
@HighExodus, пожалуйста! И действительно, это связано с тем, что сортировка не может быть установлена ​​​​в источнике данных, как в приведенном выше ответе Пола Зачковски. - person Martijn van Put; 30.07.2013

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

        protected override void OnDataSourceChanged(EventArgs e)
    {
        if ((this.Sorted && (this.DataSource != null)) && base.Created)
        {
            this.DataSource = null;
            throw new InvalidOperationException(System.Windows.Forms.SR.GetString("ComboBoxDataSourceWithSort"));
        }
        ...
        ...
    }

В таком случае вы должны были получить InvalidOperationException. Почему Ты не получил? Вот ответ:

Реализация свойства DataSource в элементе управления ComboBox перенаправляет на его реализацию базового класса (ListControl):

        public object DataSource
    {
        get
        {
            return base.DataSource;
        }
        set
        {
            base.DataSource = value;
        }
    }

А затем в DataSource базового класса:

        public object DataSource
    {
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        get
        {
            return this.dataSource;
        }
        set
        {
            if (((value != null) && !(value is IList)) && !(value is IListSource))
            {
                throw new ArgumentException(System.Windows.Forms.SR.GetString("BadDataSourceForComplexBinding"));
            }
            if (this.dataSource != value)
            {
                try
                {
                    this.SetDataConnection(value, this.displayMember, false);
                }
                catch
                {
                    this.DisplayMember = "";
                }
                if (value == null)
                {
                    this.DisplayMember = "";
                }
            }
        }
    }

Обратите внимание на молчаливый блок catch. Поскольку SetDataConnection вызывает OnDataSourceChanged, то, насколько мой анализ верен, это и есть причина. Если я ошибаюсь, поправьте меня.

person sk_ra    schedule 05.03.2014