grokuk
asked on
DataBinding an ArrayList to a ListBox and updating
Hi,
I have a ListBox which is bound to an ArrayList like so:
ArrayList *JumpPoints = new ArrayList();
ListBox *lbBeacons = new ListBox();
...etc...
lbBeacons->DataSource = JumpPoints;
lbBeacons->DisplayMember =S"BeaconString";
And all works fine until the ArrayList changes but the ListBox doesn't refresh in any way that reflects the changes. I have looked around and come across CurrencyManagers/BindingMa nagers but can find no coherent examples in VC++ that cover what I need.
Which is the best way to go to achieve this? Can anyone give a clear code example in VC++?
Many thanks.
I have a ListBox which is bound to an ArrayList like so:
ArrayList *JumpPoints = new ArrayList();
ListBox *lbBeacons = new ListBox();
...etc...
lbBeacons->DataSource = JumpPoints;
lbBeacons->DisplayMember =S"BeaconString";
And all works fine until the ArrayList changes but the ListBox doesn't refresh in any way that reflects the changes. I have looked around and come across CurrencyManagers/BindingMa
Which is the best way to go to achieve this? Can anyone give a clear code example in VC++?
Many thanks.
ASKER
I've tried reassigning the DataSource to zero and then back again to the ArrayList, but no improvement.
Have you tried to call DataBind() ?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
what i usually do is define a function which is called whenever the listbox needs to be updated...
inside this function i define and fill the arraylist, and bind it to the list box.
because the arraylist only exists in this local scope, every time this function is called the listbox is updated accordingly
i also include code at the beginning and end of the function which preserves the selected index - so if the data is refreshed on a timer, the user doesnt get interrupted.
void Reload_Data()
{
// store selected index
int index = this->Listbox->SelectedInd ex;
// create arraylist
ArrayList * data = new ArrayList();
// fill arraylist with relevant information
// ...
// bind arraylist to listbox
this->Listbox->ValueMember = S"ID";
this->Listbox->DisplayMemb er = S"Name";
this->Listbox->DataSource = data;
// restore selected index
this->Listbox->SelectedInd ex = index;
}
if you need to preserve your existing arraylist, you could pass it to this function like this
void Reload_Data(ArrayList * data)
{
// ...
}
then call it as...
Reload_Data(JumpPoints);
when you call the function, your exsiting arraylist will be copied to a new one called 'data' which will only exist in the local scope, and the function will behave as expected
hope this helps
inside this function i define and fill the arraylist, and bind it to the list box.
because the arraylist only exists in this local scope, every time this function is called the listbox is updated accordingly
i also include code at the beginning and end of the function which preserves the selected index - so if the data is refreshed on a timer, the user doesnt get interrupted.
void Reload_Data()
{
// store selected index
int index = this->Listbox->SelectedInd
// create arraylist
ArrayList * data = new ArrayList();
// fill arraylist with relevant information
// ...
// bind arraylist to listbox
this->Listbox->ValueMember
this->Listbox->DisplayMemb
this->Listbox->DataSource = data;
// restore selected index
this->Listbox->SelectedInd
}
if you need to preserve your existing arraylist, you could pass it to this function like this
void Reload_Data(ArrayList * data)
{
// ...
}
then call it as...
Reload_Data(JumpPoints);
when you call the function, your exsiting arraylist will be copied to a new one called 'data' which will only exist in the local scope, and the function will behave as expected
hope this helps
sorry forgot to mention - if you define the function with parameters (ArrayList * data) then obviously you must remove the ArrayList definition inside the function or you will get a compiler error !
I've run through the same problem with the difference that I program in C#.
But the solution should be the same.
Here is what I did....
ArrayList *JumpPoints = new ArrayList();
ListBox *lbBeacons = new ListBox();
lbBeacons->DataSource = JumpPoints;
lbBeacons->DisplayMember =S"BeaconString";
/****************whatever changes your arraylist***************** **/
/************************* ********** ********** ****/
/*****************refreshi ng!!!! ************/
// Unbind the grid
lbBeacons->DataSource = null;
// Bind the grid
lbBeacons->DataSource = JumpPoints;
// This will refresh the currency manager.....
CurrencyManager currencymanager = (CurrencyManager)lbBeacons ->BindingC ontext[Jum pPoints];
currencymanager->Refresh() ;
/*****************finish refreshing!!!! ************/
Hope this works for you.......
Fernando de la Garza
But the solution should be the same.
Here is what I did....
ArrayList *JumpPoints = new ArrayList();
ListBox *lbBeacons = new ListBox();
lbBeacons->DataSource = JumpPoints;
lbBeacons->DisplayMember =S"BeaconString";
/****************whatever changes your arraylist*****************
/*************************
/*****************refreshi
// Unbind the grid
lbBeacons->DataSource = null;
// Bind the grid
lbBeacons->DataSource = JumpPoints;
// This will refresh the currency manager.....
CurrencyManager currencymanager = (CurrencyManager)lbBeacons
currencymanager->Refresh()
/*****************finish refreshing!!!! ************/
Hope this works for you.......
Fernando de la Garza
ASKER
Thanks to those who've answered, but I'm still looking for a working VC++ (.NET) example.
Setting the DataSource to NULL and then back to the ArrayList does almost work, but it leaves a number of 'empty' items in the ListBox (despite reassigning the Display and Value Members).
The CurrencyManager approach of Fernando looks like the right sort of thing, but C++ handles the BindingContext in a rather different way to C#. Or at least, I can't find any equivalent to the lbBeacons->BindContect[Jum pPoints] indirection that works. Maybe I'm missing something obvious?
Still searching....
Setting the DataSource to NULL and then back to the ArrayList does almost work, but it leaves a number of 'empty' items in the ListBox (despite reassigning the Display and Value Members).
The CurrencyManager approach of Fernando looks like the right sort of thing, but C++ handles the BindingContext in a rather different way to C#. Or at least, I can't find any equivalent to the lbBeacons->BindContect[Jum
Still searching....
i think you will find my method shown above works just fine. i have millions of listboxes, comboboxes and datagrids in my applications, which all use that method.
to re-iterate - define and fill the arraylist within a function. bind the arraylist to the listbox in the same function. whenever you want to update the listbox, simply call the function. because the arraylist is in local scope to that function, every time you call it the listbox sees a 'new' arraylist, and updates itself with the new data.
to re-iterate - define and fill the arraylist within a function. bind the arraylist to the listbox in the same function. whenever you want to update the listbox, simply call the function. because the arraylist is in local scope to that function, every time you call it the listbox sees a 'new' arraylist, and updates itself with the new data.
and of course, every time the list is refreshed, the previous arraylist no longer has any references to it, and so the garbage collector will deal with it accordingly
ASKER
Thanks Statick but I was hoping to find a solution that avoided re-iterating through the full list each time.
It turns out that I owe an apology to Svetlin_Panayotov as his solution does in fact work perfectly if you also reassign the DisplayMember as well as the DataSource.
In Short:
lbBeacons->DataSource = NULL;
lbBeacons->DataSource = JumpPoints;
lbBeacons->DisplayMember =S"BeaconString";
Does the trick.
It turns out that I owe an apology to Svetlin_Panayotov as his solution does in fact work perfectly if you also reassign the DisplayMember as well as the DataSource.
In Short:
lbBeacons->DataSource = NULL;
lbBeacons->DataSource = JumpPoints;
lbBeacons->DisplayMember =S"BeaconString";
Does the trick.
I think you'll need to re set the DataSource