1

Have two ListBox. Double-click on the lbSubject element, adds this element to the second lbSelectedSubject. Provided that this element is not already in lbSelectedSubject. The check for the presence of elements goes through the List<int> to which ValueMember is added.

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;
}

The addition is correct. In the sense that the person creates and displays the Title. The problem is the reverse process. Remove from lbSelectedSubject. A string in LbSelectedSubject_MouseDoubleClick throws an exception:

lbSelectedSubject.SelectedValue

System.NullReferenceException: "object Reference not pointing to object instance." System.Windows.Forms.ListControl.SelectedValue.get returned null.

This lbSelectedSubject.Items contains the correct item and settings for Display and Value. SelectedItem also normally, not null.

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

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

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

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

The same item in the list lbSubject contains the correct value Value, not null.

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

Why after adding in the lbSelectedSubject through the line

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

It turns out that SelectedValue does not work? Under other equal conditions lbSubject.

UPDATE It is not duplicate.

  • You have not set any kind of DataSource on the lbselectedSubject list. So no SelectedValue is available there – Steve Jun 23 '19 at 15:23
  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Ňɏssa Pøngjǣrdenlarp Jun 23 '19 at 15:25
  • @ŇɏssaPøngjǣrdenlarp I don't know if this case is documented in that duplicate – Steve Jun 23 '19 at 15:31
  • @Steve how to fix? I do not understand how implement –  Jun 23 '19 at 15:39

1 Answers1

1

You cannot use the SelectedValue property if the ListBox has no DataSource.
A simple workaround is to provide the second listbox with an empty datasource of the same type you have set for the first one.

So suppose to have your first ListBox binded to a class of this type

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

Now when you build the first listbox DataSource you build as well the second DataSource with

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
    .....

}

Finally in the MouseDoubleClick event you can reference your data with SelectedItem and 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);
    }
}

Also, a minor problem. Never set the DisplayMember and ValueMember after setting the Datasource property. Doing in that order will cause the Binding to happen two times, once when you set the Datasource and another one when you set the ValueMember.

Steve
  • 213,761
  • 22
  • 232
  • 286
  • `Never set the DisplayMember and ValueMember after setting the Datasource property`. I would do so. But I have problem. When I try to do DataSource through BindingSource for ListBox is OK. But when I do it for ComboBox and CheckedListBox are not OK. As soon as I reversed the assignment of the DataSource and DisplayMember - works ¯\_(ツ)_/¯ –  Jun 23 '19 at 17:21
  • Sorry but I cannot speculate on that problem. Perhaps a new question will help you more. However, are you now able to remove the selected object from the second list? – Steve Jun 23 '19 at 17:29
  • 1
    Your answer helped me. Now I can remove an item so as and wanted to. I needed change an `anonymous type` to `MyItem` class for EF Core (`select new MyItem{}`). Okay, I will create new question. –  Jun 23 '19 at 17:38
  • Glad to be of help. See you again on SO – Steve Jun 23 '19 at 17:39
  • maybe you know [post](https://stackoverflow.com/questions/56726783/display-and-value-members-after-and-before-assignment-datasource) –  Jun 23 '19 at 19:30
  • or this [post](https://stackoverflow.com/questions/56751453/a-value-didnt-updated-entity-framework) –  Jun 25 '19 at 12:14