Reputation: 11
Background
The application has a list view binded to a list of "Jobs", of which the properties are editable by some comboboxes (with two way binding). The data context of the comboboxes is changed to the currently selected job
via the SelectionChanged
event of the list view.
The combobox value is bound to a property of Job. The itemssource
of the job is changed to completely different list upon DataContextChanged
.
Issue
The binded property linked to the combobox of Job is set to null when changing the DataContext.
By clicking through the list of Jobs, all the properties bound to any combobox are set to null.
Assumed Problem
I may be incorrect in this assumtion...
As the datacontext
is switched, either the old selected Job
or the new selected Job
is set to null as the itemsource does nto contain the value stores in on of the either the new or old selected Job
.
Debugging Attempts (Edit)
I've noticed the the value of the property of the Job
was set to null before the SelectedItem
of the list of jobs was changed.
Question
How can the value of the binded property of Job
be preserved when switching the datacontext of the ComboBox to an itemsource that does not contain SelectedValue
?
Relevant Code (Abridged - Binding to other widgets works as expected)
<ComboBox x:Name="ContactField" Grid.Column="1" Grid.Row="3" Margin="2,1" Grid.ColumnSpan="3" DisplayMemberPath="Value" SelectedValuePath="Id" SelectedValue="{Binding Contact,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectionChanged="ContactField_SelectionChanged"/>
Code Behind - Changing Items Source
private void UpdateCustomerDependancies()
{
imprintDataSetTableAdapters.CustomerContactsTableTableAdapter rpcdtta = new imprintDataSetTableAdapters.CustomerContactsTableTableAdapter();
IList<ComboData> customers = new List<ComboData>();
if (LeftFieldPanel.DataContext != null) //Where LeftFieldPanel contains all comboboxes
{
Job currentJob = (Job)LeftFieldPanel.DataContext;
foreach (DataRow item in rpcdtta.GetDataBy(currentJob.CustomerCode).Rows)
{
customers.Add(new ComboData() { Id = item.ItemArray[0].ToString(), Value = item.ItemArray[1].ToString() });
}
ContactField.ItemsSource = customers;
}
}
Code Behind - Changing Data Context
private void jobTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if (jobTree.SelectedItem.GetType() == typeof(Job))
{
DelGrid.Visibility = Visibility.Hidden;
Job j = (Job)jobTree.SelectedItem;
MessageBox.Show(j.Contact);
LeftFieldPanel.DataContext = j; //Switch datacontext
RightFieldPanel.DataContext = j; //switchdata context
}
}
Upvotes: 0
Views: 258
Reputation: 11
According to this answer, and my own research, it is not possible to simply bind and hope for this best. Therefore, my workaorund to this solution is the following. I have generalised the code to make it applicable to other circumstances.
1) Upon the change of datacontext, append new items to the list, without removing old items:
private void ListView1_SelectedItemChanged(...) {
List<ComboData> comboitems = ((IList<ComboData>)ComboBox1.ItemsSource).ToList();
//Add new items to comboitems here
ComboBox1.ItemsSource = comboitems; //Rebind
}
2) Upon opening the dropdown of the combobox, get the itemsource and remove old items only
private void ComboBox1_DropDownOpened(...) {
List<ComboData> comboitems = ((IList<ComboData>)ComboBox1.ItemsSource).ToList();
//Remove old items from comboitems here
ComboBox1.ItemsSource = comboitems; //Rebind
}
Apologies if this is not clear enough, I felt that posting the real code would make it rather difficult to understand out of the context.
This has solved my own issue.
Alternate Solution
See above and add items without remove old ones. Then replace the entire itemssource only on a dropdownopened
event.
Upvotes: 1