Я делаю простое приложение WinForms, и у меня возникает странная проблема.

Моя форма:

enter image description here

Это максимально просто: 3 поля со списком и две кнопки - ОК и Отмена.

Просмотр:

private void applyOrderButton_Click(object sender, EventArgs e)
    {
        List<string> testList = new List<string>()
        {
            "A",
            "B",
            "C"
        };

        comboBox1st.DataSource = testList;
        comboBox2nd.DataSource = testList;
        comboBox3rd.DataSource = testList;

        comboBox1st.SelectedIndex = 2;
        comboBox2nd.SelectedIndex = 1;
        comboBox3rd.SelectedIndex = 0;
        //Presenter.DoTest();
    }

Что происходит после вызова метода applyOrderButton_Click() (это происходит после нажатия кнопки ОК), все мои поля со списком меняют выбранную позицию. Однако каждый из этих комбинированных списков имеет один и тот же выбранный индекс - в данном конкретном случае это будет «А».

Затем я изменяю значение comboBox selectedIndex с помощью курсора (например, я выбираю 3-й comboBox, чтобы показать «C»), изменение выполняется для всех трех comboBox. Что я делаю не так?

5
bartosz.baczek 28 Окт 2015 в 10:13

2 ответа

Лучший ответ

Вы столкнулись с чем-то, что присутствует в фоновом режиме WinForms, под названием «CurrencyManager».

Его задача - синхронизировать «текущую запись» между всеми привязываемыми элементами управления, которые ссылаются на один и тот же источник данных.

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

Одним из преимуществ этого является то, что вы можете легко добавить форму, которая редактирует список объектов, привязывает текстовые поля и т. Д. К свойствам одного из объектов и добавляет навигатор, который позволяет вам переходить к следующей или предыдущей строке. Вам не нужно вручную гарантировать, что все текстовые поля относятся к правильному объекту, CurrencyManager сделает все это за вас.

Однако в вашем случае, поскольку вы связали один и тот же источник данных со всеми тремя полями со списком, CurrencyManager гарантирует, что все три выберут одну и ту же строку. Если вы выберете новую строку в одном из полей со списком, CurrencyManager перейдет и исправит все остальные, чтобы они ссылались на ту же строку.

Исправить это можно разными способами:

  1. Вы можете переопределить контекст привязки для каждого поля со списком:

    comboBox2nd.BindingContext = new BindingContext();
    comboBox3rd.BindingContext = new BindingContext();
    

    Обратите внимание, что если вы пойдете по этому маршруту, вам необходимо сделать это до назначения свойств SelectedIndex или SelectedItem, в противном случае CurrencyManager обновит два других поля со списком, прежде чем вы назначите новый BindingContexts.

  2. Вы можете назначить отдельные источники данных для каждого поля со списком:

    combobox2nd.DataSource = testList.ToList();
    combobox3rd.DataSource = testList.ToList();
    
10
Lasse V. Karlsen 28 Окт 2015 в 07:31

Просто назначьте новый контекст другим ComboBox, например:

List<string> testList = new List<string>()
    {
        "A",
        "B",
        "C"
    };

comboBox1st.DataSource = testList;

comboBox2nd.BindingContext = new BindingContext();
comboBox2nd.DataSource = testList;

comboBox3rd.BindingContext = new BindingContext();
comboBox3rd.DataSource = testList;

comboBox1st.SelectedIndex = 2;
comboBox2nd.SelectedIndex = 1;
comboBox3rd.SelectedIndex = 0;

CurrencyManager используется для синхронизации элементов управления с привязкой к данным (отображение данных из одной записи). Объект CurrencyManager делает это, управляя коллекцией связанных данных, предоставленных источником данных. Для каждого источника данных, связанного с формой Windows Form, форма поддерживает по крайней мере один CurrencyManager. Поскольку с формой может быть связано более одного источника данных, объект BindingContext управляет всеми объектами CurrencyManager для любой конкретной формы. В более широком смысле, все контейнерные элементы управления имеют по крайней мере один объект BindingContext для управления своими CurrencyManager.

7
StepUp 28 Окт 2015 в 08:38