Сведения о вопросе

nikolya

16:03, 1st July, 2020

Теги

c#   winforms   data-binding    

WinForms ComboBox привязка данных попалась

Просмотров: 444   Ответов: 2

Предположим, что вы делаете что-то вроде следующего

List<string> myitems = new List<string>
{
    "Item 1",
    "Item 2",
    "Item 3"
};

ComboBox box = new ComboBox();
box.DataSource = myitems;

ComboBox box2 = new ComboBox();
box2.DataSource = myitems

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

Теперь я знаю, что массивы всегда передаются по ссылке (узнал это, когда узнал C :D), но с какой стати поля со списком будут меняться вместе? Я не верю, что элемент управления combo box вообще изменяет коллекцию.

В качестве обходного пути, не это бы достичь функциональности, которая ожидается / желаемый

ComboBox box = new ComboBox();
box.DataSource = myitems.ToArray();



  Сведения об ответе

VERSUION

18:03, 1st July, 2020

Это связано с тем, как привязки данных настраиваются в рамках dotnet, особенно BindingContext . На высоком уровне это означает, что если вы не указали иное, то каждая форма и все элементы управления формы имеют один и тот же BindingContext . При установке свойства DataSource ComboBox будет использовать BindingContext для получения ConcurrenyMangager , который обертывает список. ConcurrenyManager отслеживает такие вещи, как текущая выбранная позиция в списке.

Когда вы устанавливаете DataSource второго ComboBox , он будет использовать тот же BindingContext (формы), который даст ссылку на тот же ConcurrencyManager , что и выше, используемый для настройки Привязок данных.

Чтобы получить более подробное объяснение, смотрите BindingContext .


  Сведения об ответе

VERSUION

18:03, 1st July, 2020

Лучшим обходным путем (в зависимости от размера источника данных) является объявление двух объектов BindingSource (new as of 2.00), связывающих коллекцию с ними, а затем связывающих их с comboboxes.

Я прилагаю полный пример.

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

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        private BindingSource source1 = new BindingSource();
        private BindingSource source2 = new BindingSource();

        public Form1()
        {
            InitializeComponent();
            Load += new EventHandler(Form1Load);
        }

        void Form1Load(object sender, EventArgs e)
        {
            List<string> myitems = new List<string>
            {
                "Item 1",
                "Item 2",
                "Item 3"
            };

            ComboBox box = new ComboBox();
            box.Bounds = new Rectangle(10, 10, 100, 50);
            source1.DataSource = myitems;
            box.DataSource = source1;

            ComboBox box2 = new ComboBox();
            box2.Bounds = new Rectangle(10, 80, 100, 50);
            source2.DataSource = myitems;
            box2.DataSource = source2;

            Controls.Add(box);
            Controls.Add(box2);
        }
    }
}

Если вы хотите запутать себя еще больше, то попробуйте всегда объявлять привязки в конструкторе. Это может привести к некоторым действительно любопытным ошибкам, поэтому я всегда связываюсь в событии Load.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться