Не находит ValueMember после добавления из другого ListBox - PullRequest
1 голос
/ 23 июня 2019

Есть два ListBox.Двойной щелчок по элементу lbSubject добавляет этот элемент ко второму lbSelectedSubject.При условии, что этого элемента еще нет в lbSelectedSubject.Проверка на наличие элементов проходит через List<int>, к которому добавляется ValueMember.

List<int> selectedValueSubject;

private void Form_Load(object sender, EventArgs e)
{
    selectedValueSubject = new List<int>();
    lbSelectedSubject.DisplayMember = "Title";
    lbSelectedSubject.ValueMember = "Id";

    lbSubject.DataSource = bindingSubjectDefault;
    lbSubject.DisplayMember = "Title";
    lbSubject.ValueMember = "Id";
}

private void LbSubject_MouseDoubleClick(object sender, MouseEventArgs e)
{
    int index = lbSubject.IndexFromPoint(e.Location);
    if (index != ListBox.NoMatches)
    {
        int id = (int)lbSubject.SelectedValue;
        if (IsNotConstrain(id, selectedValueSubject.ToArray()))
        {
            selectedValueSubject.Add(id);
            lbSelectedSubject.Items.Add(lbSubject.Items[index]);
        }
    }
}

private void LbSelectedSubject_MouseDoubleClick(object sender, MouseEventArgs e)
{
    int index = lbSelectedSubject.IndexFromPoint(e.Location);
    if (index != ListBox.NoMatches)
    {
        selectedValueSubject.Remove((int)lbSelectedSubject.SelectedValue);
        lbSelectedSubject.Items.RemoveAt(index);
    }
}

private bool IsNotConstrain(int id, int[] keys)
{
    bool result = true;
    foreach(int key in keys)
    {
        if (key == id)
        {
            result = false;
            break;
        }
    }

    return result;
}

Добавление является правильным.В том смысле, что человек создает и отображает Title.Проблема в обратном процессе.Удалить из lbSelectedSubject.Строка в LbSelectedSubject_MouseDoubleClick вызывает исключение:

lbSelectedSubject.SelectedValue

System.NullReferenceException: "Ссылка на объект не указывает на экземпляр объекта."System.Windows.Forms.ListControl.SelectedValue.get вернул null.

Этот lbSelectedSubject.Items содержит правильный элемент и настройки для Display и Value.SelectedItem также обычно, не ноль.

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

Этот же элемент в списке lbSubject содержит правильное значение Value, а не null.

введите сюда описание изображения

Почему после добавления в lbSelectedSubject через строку

lbSelectedSubject.Items.Add(lbSubject.Items[index]);

Получается, что SelectedValue не работает?При прочих равных условиях lbSubject.

ОБНОВЛЕНИЕ Не дублируется.

1 Ответ

1 голос
/ 23 июня 2019

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

Поэтому предположим, что ваш первый ListBox связан с классом этого типа

public class TitleData
{
    public int Id { get; set; }
    public string Title{ get; set; }
}

Теперь, когда вы создаете первый список DataSource, вы создаете также второй DataSource с

public void Form_Load(object sender, EventArgs e)
{
    selectedValueSubject = new List<int>();
    bsSelected.DataSource = new List<TitleData>();

    lbSelectedSubject.DisplayMember = "Title";
    lbSelectedSubject.ValueMember = "Id";
    lbSelectedSubject.DataSource = bsSelected; // <= this is a BindingSource at the class level
    .....

}

Наконец, всобытие MouseDoubleClick, на которое вы можете ссылаться на ваши данные с помощью SelectedItem и SelectedValue

private void LbSelectedSubject_MouseDoubleClick(object sender, MouseEventArgs e)
{
    int index = lbSelectedSubject.IndexFromPoint(e.Location);
    if (index != ListBox.NoMatches)
    {
        // Always do this before removing the element from the BindingSource
        selectedValueSubject.Remove((int)lbSelectedSubject.SelectedValue);

        bsSelected.Remove(lbSelectedSubject.SelectedItem);
        // lbSelectedSubject.Items.RemoveAt(index);
    }
}

Кроме того, небольшая проблема.Никогда не устанавливайте DisplayMember и ValueMember после установки свойства источника данных.Выполнение в таком порядке приведет к тому, что привязка произойдет два раза: один раз при установке источника данных и еще один при установке ValueMember.

...