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