Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > Raising INotifyPropertyChanged on object also resets current item on list
 

Raising INotifyPropertyChanged on object also resets current item on list

I have a question about databinding. I will use a very simple example to illustrate the question.

i have two classes with properties, including is a bindinglist collection with another class.
both classes implement inotifypropertychanged :

    public

 class

 Plane : INotifyPropertyChanged
    {
        public

 string

 PlaneName
        {
            get

 { return

 _PlaneName; }
            set

 { _PlaneName = value; onpropertychanged("PlaneName"

); }
        }
        private

 string

 _PlaneName;

        public

 BindingList<Passenger> Passengers
        {
            get

 { return

 _Passengers; }
            set

 { _Passengers = value; onpropertychanged("Passengers"

); }
        }
        private

 BindingList<Passenger> _Passengers;

        #region

 INotifyPropertyChanged Members

        public

 event

 PropertyChangedEventHandler PropertyChanged;

        private

 void

 onpropertychanged(string

 pn)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if

 (handler != null

)
            {
                handler(this

, new

 PropertyChangedEventArgs(pn));
            }
        }

        #endregion


    }

    public

 class

 Passenger : INotifyPropertyChanged
    {
        public

 string

 Name
        {
            get

 { return

 _Name; }
            set

 { _Name = value; onpropertychanged("Name"

); }
        }
        private

 string

 _Name;

        public

 int

 Age
        {
            get

 { return

 _Age; }
            set

 { _Age = value; onpropertychanged("Age"

); }
        }
        private

 int

 _Age;


        #region

 INotifyPropertyChanged Members

        public

 event

 PropertyChangedEventHandler PropertyChanged;

        private

 void

 onpropertychanged( string

 pn )
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if

 (handler != null

)
            {
                handler(this

, new

 PropertyChangedEventArgs(pn));
            }
        }

        #endregion


    }


my testform is a simple form with a textbox for simple properties and a listview for the list.

            listPlanes.DataSource = planes;
            listPlanes.DisplayMember = "PlaneName"

;

            txtPlaneName.DataBindings.Add("Text"

, planes, "PlaneName"

, false

, DataSourceUpdateMode.OnPropertyChanged);

            listPassenger.DataSource = planes;
            listPassenger.DisplayMember = "Passengers.Name"

;

            txtAge.DataBindings.Add("Text"

, planes, "Passengers.Age"

, false

, DataSourceUpdateMode.OnPropertyChanged);            
            txtName.DataBindings.Add("Text"

, planes, "Passengers.Name"

, false

, DataSourceUpdateMode.OnPropertyChanged);



Now everything works fine, i can choose a passenger from the list, edit the passenger name in the textbox. this change also updates the passenger name in the passenger list.

But when i choose a passenger from the list and then edit the name of the plane (which is in the same object as the passenger list) it also resets the current selected passenger to the first item of the list.

Is it possible to avoid this? in other words, i want to select the second passenger and then edit the planename without the selected passenger is set to the first passenger.

thanx in advance
Dennis de Jong


dennis.de.jong  Friday, September 18, 2009 1:37 PM

Hi,

Seems you need to add other code to keep the selected index of Passengers bindinglist when plane bindinglist changed.


Keep the selectedIndex when Planes listChanged. Then reset the selectedIndex in ListPassenger SelectedIndexChanged event.

Besides, planes.ListChanged event must be registered before being bound to listbox. This will make the bindinglist.listchanged event be triggered before listbox.selectedIndexChanged event.

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

BindingList<Plane> planes = new BindingList<Plane>();

BindingList<Plane> planes1 = new BindingList<Plane>();

BindingList<Passenger> Passengers = new BindingList<Passenger>();

Passengers.Add(new Passenger("cc", 1));

Passengers.Add(new Passenger("cc", 12));

Passengers.Add(new Passenger("cc", 13));

Passengers.Add(new Passenger("cc", 14));

BindingList<Passenger> Passengers1 = new BindingList<Passenger>();

Passengers1.Add(new Passenger("aa", 1));

Passengers1.Add(new Passenger("aa", 12));

Passengers1.Add(new Passenger("aa", 13));

Passengers1.Add(new Passenger("aa", 14));

planes.Add(new Plane("test", Passengers));

planes.Add(new Plane("test", Passengers1));

planes.ListChanged += new ListChangedEventHandler(planes_ListChanged);

listPlanes.DataSource = planes;

listPlanes.DisplayMember = "PlaneName";

txtPlaneName.DataBindings.Add("Text", planes, "PlaneName", false, DataSourceUpdateMode.OnPropertyChanged);

listPassenger.DataSource = planes;

listPassenger.DisplayMember = "Passengers.Name";

txtAge.DataBindings.Add("Text", planes, "Passengers.Age", false, DataSourceUpdateMode.OnPropertyChanged);

txtName.DataBindings.Add("Text", planes, "Passengers.Name", false, DataSourceUpdateMode.OnPropertyChanged);

listPassenger.SelectedIndexChanged += new EventHandler(listPassenger_SelectedIndexChanged);

}

bool changed = false;

int index = 0;

void planes_ListChanged(object sender, ListChangedEventArgs e)

{

changed = true;

index = listPassenger.SelectedIndex;

}

void listPassenger_SelectedIndexChanged(object sender, EventArgs e)

{

if (changed == true && index != 0)

{

listPassenger.SelectedIndex = index;

changed = false;

index = 0;

}

}

}

public class Plane : INotifyPropertyChanged

{

private string _PlaneName;

private BindingList<Passenger> _Passengers;

public Plane(string strPlaneName, BindingList<Passenger> ListPassengers)

{

this._PlaneName = strPlaneName;

this._Passengers = ListPassengers;

}

public string PlaneName

{

get

{

return _PlaneName;

}

set

{

_PlaneName = value; onpropertychanged("PlaneName");

}

}

public BindingList<Passenger> Passengers

{

get

{

return _Passengers;

}

set

{

_Passengers = value; onpropertychanged("Passengers");

}

}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

private void onpropertychanged(string pn)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

{

handler(this, new PropertyChangedEventArgs(pn));

}

}

#endregion

}

public class Passenger : INotifyPropertyChanged

{

private string _Name;

private int _Age;

public Passenger(string strName, int iAge)

{

this._Name = strName;

this._Age = iAge;

}

public string Name

{

get

{

return _Name;

}

set

{

_Name = value; onpropertychanged("Name");

}

}

public int Age

{

get

{

return _Age;

}

set

{

_Age = value; onpropertychanged("Age");

}

}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

private void onpropertychanged(string pn)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

{

handler(this, new PropertyChangedEventArgs(pn));

}

}

#endregion

}

Best regards,

Ling Wang


Please remember to click “Mark as Answer�on the post that helps you, and to click “Unmark as Answer�if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
Ling Wang  Friday, September 25, 2009 9:23 AM

Hi,

Seems you need to add other code to keep the selected index of Passengers bindinglist when plane bindinglist changed.


Keep the selectedIndex when Planes listChanged. Then reset the selectedIndex in ListPassenger SelectedIndexChanged event.

Besides, planes.ListChanged event must be registered before being bound to listbox. This will make the bindinglist.listchanged event be triggered before listbox.selectedIndexChanged event.

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

BindingList<Plane> planes = new BindingList<Plane>();

BindingList<Plane> planes1 = new BindingList<Plane>();

BindingList<Passenger> Passengers = new BindingList<Passenger>();

Passengers.Add(new Passenger("cc", 1));

Passengers.Add(new Passenger("cc", 12));

Passengers.Add(new Passenger("cc", 13));

Passengers.Add(new Passenger("cc", 14));

BindingList<Passenger> Passengers1 = new BindingList<Passenger>();

Passengers1.Add(new Passenger("aa", 1));

Passengers1.Add(new Passenger("aa", 12));

Passengers1.Add(new Passenger("aa", 13));

Passengers1.Add(new Passenger("aa", 14));

planes.Add(new Plane("test", Passengers));

planes.Add(new Plane("test", Passengers1));

planes.ListChanged += new ListChangedEventHandler(planes_ListChanged);

listPlanes.DataSource = planes;

listPlanes.DisplayMember = "PlaneName";

txtPlaneName.DataBindings.Add("Text", planes, "PlaneName", false, DataSourceUpdateMode.OnPropertyChanged);

listPassenger.DataSource = planes;

listPassenger.DisplayMember = "Passengers.Name";

txtAge.DataBindings.Add("Text", planes, "Passengers.Age", false, DataSourceUpdateMode.OnPropertyChanged);

txtName.DataBindings.Add("Text", planes, "Passengers.Name", false, DataSourceUpdateMode.OnPropertyChanged);

listPassenger.SelectedIndexChanged += new EventHandler(listPassenger_SelectedIndexChanged);

}

bool changed = false;

int index = 0;

void planes_ListChanged(object sender, ListChangedEventArgs e)

{

changed = true;

index = listPassenger.SelectedIndex;

}

void listPassenger_SelectedIndexChanged(object sender, EventArgs e)

{

if (changed == true && index != 0)

{

listPassenger.SelectedIndex = index;

changed = false;

index = 0;

}

}

}

public class Plane : INotifyPropertyChanged

{

private string _PlaneName;

private BindingList<Passenger> _Passengers;

public Plane(string strPlaneName, BindingList<Passenger> ListPassengers)

{

this._PlaneName = strPlaneName;

this._Passengers = ListPassengers;

}

public string PlaneName

{

get

{

return _PlaneName;

}

set

{

_PlaneName = value; onpropertychanged("PlaneName");

}

}

public BindingList<Passenger> Passengers

{

get

{

return _Passengers;

}

set

{

_Passengers = value; onpropertychanged("Passengers");

}

}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

private void onpropertychanged(string pn)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

{

handler(this, new PropertyChangedEventArgs(pn));

}

}

#endregion

}

public class Passenger : INotifyPropertyChanged

{

private string _Name;

private int _Age;

public Passenger(string strName, int iAge)

{

this._Name = strName;

this._Age = iAge;

}

public string Name

{

get

{

return _Name;

}

set

{

_Name = value; onpropertychanged("Name");

}

}

public int Age

{

get

{

return _Age;

}

set

{

_Age = value; onpropertychanged("Age");

}

}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

private void onpropertychanged(string pn)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

{

handler(this, new PropertyChangedEventArgs(pn));

}

}

#endregion

}

Best regards,

Ling Wang


Please remember to click “Mark as Answer�on the post that helps you, and to click “Unmark as Answer�if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
Ling Wang  Friday, September 25, 2009 9:23 AM
Thanks for answering Ling,
Your suggestion works fine, however i see it as a work-around.
Is my assumption correct that the reset of the current selected item is behavior of the databinding itself?
best regards
Dennis

dennis.de.jong  Tuesday, September 29, 2009 8:22 AM

You can use google to search for other answers

Custom Search

More Threads

• OWC charts lables
• disabling second combobox until selected index is changed in the first combobox in a datagrid view
• Header Text Alignment in Datagrid
• VS2005 DataGridView
• Binding a textbox to the main Data Connection
• datagridview checkboxes select with mouse drag
• get the selected text from a combobox in its SelectionChangeCommitted event
• Using More the One RowFilter in a Datagrid
• Textbox updated by listbox selection
• Add/Remove Programs lookalike control