I have a data context (UserPreferences) assigned to my main window, and a textbox that binds two-way to a property within one of the data context\'s properties
Alright, I was able to determine the problem and get it resolved. It turned out to be a compilation of things causing this.
First, my model.
UserPreferences <-- MainWindow is data bound to this.
[Serializable]
public class UserPreferences : INotifyPropertyChanged
{
private CollectionDevice selectedCollectionDevice;
public UserPreferences()
{
this.AvailableCollectionDevices = new List();
var yuma1 = new CollectionDevice
{
BaudRate = 4800,
ComPort = 31,
DataPoints = 1,
Name = "Trimble Yuma 1",
WAAS = true
};
var yuma2 = new CollectionDevice
{
BaudRate = 4800,
ComPort = 3,
DataPoints = 1,
Name = "Trimble Yuma 2",
WAAS = true
};
var toughbook = new CollectionDevice
{
BaudRate = 4800,
ComPort = 3,
DataPoints = 1,
Name = "Panasonic Toughbook",
WAAS = true
};
var other = new CollectionDevice
{
BaudRate = 0,
ComPort = 0,
DataPoints = 0,
Name = "Other",
WAAS = false
};
this.AvailableCollectionDevices.Add(yuma1);
this.AvailableCollectionDevices.Add(yuma2);
this.AvailableCollectionDevices.Add(toughbook);
this.AvailableCollectionDevices.Add(other);
this.SelectedCollectionDevice = this.AvailableCollectionDevices.First();
}
///
/// Gets or sets the GPS collection device.
///
public CollectionDevice SelectedCollectionDevice
{
get
{
return selectedCollectionDevice;
}
set
{
selectedCollectionDevice = value;
if (selectedCollectionDevice.Name == "Other")
{
this.AvailableCollectionDevices[3] = value;
}
this.OnPropertyChanged("SelectedCollectionDevice");
}
}
///
/// Gets or sets a collection of devices that can be used for collecting GPS data.
///
[Ignore]
[XmlIgnore]
public List AvailableCollectionDevices { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
///
/// Notifies objects registered to receive this event that a property value has changed.
///
/// The name of the property that was changed.
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
In the setter for the SelectedCollectionDevice I was not looking to see if the selected device was other. All of the other devices (yuma1, panasonic etc) have pre-determined property values that are never changed. When the user selects "Other" the textbox's are displayed and they can manually enter the data. The problem was that when the manually entered data was restored from the database during the window loading, I was not assigning the custom data in SelectedCollectionDevice to the corresponding object in the collection.
During window load, the Combobox.SelectedItem was set to the index of the SelectedCollectionDevice. The Combobox.ItemsSource was set to the AvailableCollectionDevices collection.
this.CollectionDevice.SelectedIndex =
viewModel.AvailableCollectionDevices.IndexOf(
viewModel.AvailableCollectionDevices.FirstOrDefault(
acd => acd.Name == viewModel.SelectedCollectionDevice.Name));
When the above code is executed, the combo box pulls the default object from its data source, which has all of the values set to zero. Within the combo box's SelectionChanged event I assigned the Data Context SelectedCollectionDevice to the zero'd out item associated with the combo box.
private void CollectionDeviceSelected(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0 && e.AddedItems[0] is CollectionDevice)
{
// Assign the view models SelectedCollectionDevice to the device selected in the combo box.
var device = e.AddedItems[0] as CollectionDevice;
((Models.UserPreferences)this.DataContext).SelectedCollectionDevice = device;
// Check if Other is selected. If so, we have to present additional options.
if (device.Name == "Other")
{
OtherCollectionDevicePanel.Visibility = Visibility.Visible;
}
else if (OtherCollectionDevicePanel.Visibility == Visibility.Visible)
{
OtherCollectionDevicePanel.Visibility = Visibility.Collapsed;
}
}
}
So long story short, I added the code above in the setter for the SelectedCollectionDevice to apply the value to the AvailableCollectionDevices List<>. This way, when the combo box has the "Other" value selected, it pulls the value from the collection with the correct data. During deserialization, I am just deserializing the SelectedCollectionDevice and not the List<> which is why the data was always being overwrote when the window first loaded.
This also explains why re-assigning the the data context SelectedCollectionDevice property with the local viewModel.SelectedCollectionDevice was working. I was replacing the zero'd out object associated with the combo box, which had set the data context during the SelectionChanged event. I am not able to set the DataContext in the XAML and remove the manual assignment.
Thanks for all of the help, it helped me narrow down my debugging until I finally resolved the issue. Much appreciated!