We have run into a problem where
.Equals
and .GetHashCode
methods overwritten to be considered equal..EndCurrentEdit()
on window 2 is triggering a binding update for Window 1BindingContext
We have discovered the problem has to do with calling
((PropertyManager)ctrl.BindingContext[dataSource]).EndCurrentEdit();
If we change that to
((PropertyManager)ctrl.BindingContext[dataSource, dataMember]).EndCurrentEdit();
It works correctly. It also works correctly if we remove our .Equals
and .GetHashCode
overrides so the two object models are no longer considered equal.
That doesn't make sense to me because the windows are the same, so the dataMember
property would be the same too.
From this link, I believe the definition of these calls is:
public BindingManagerBase this[object dataSource] {
get {
return this[dataSource, ""];
}
}
public BindingManagerBase this[object dataSource, string dataMember] {
get {
return EnsureListManager(dataSource, dataMember);
}
internal BindingManagerBase EnsureListManager(object dataSource, string dataMember) {
BindingManagerBase bindingManagerBase = null;
if (dataMember == null)
dataMember = "";
// Check whether data source wants to provide its own binding managers
// (but fall through to old logic if it fails to provide us with one)
//
if (dataSource is ICurrencyManagerProvider) {
bindingManagerBase = (dataSource as ICurrencyManagerProvider).GetRelatedCurrencyManager(dataMember);
if (bindingManagerBase != null) {
return bindingManagerBase;
}
}
// Check for previously created binding manager
//
HashKey key = GetKey(dataSource, dataMember);
WeakReference wRef;
wRef = listManagers[key] as WeakReference;
if (wRef != null)
bindingManagerBase = (BindingManagerBase) wRef.Target;
if (bindingManagerBase != null) {
return bindingManagerBase;
}
if (dataMember.Length == 0) {
// No data member specified, so create binding manager directly on the data source
//
if (dataSource is IList || dataSource is IListSource) {
// IListSource so we can bind the dataGrid to a table and a dataSet
bindingManagerBase = new CurrencyManager(dataSource);
}
else {
// Otherwise assume simple property binding
bindingManagerBase = new PropertyManager(dataSource);
}
}
else {
// Data member specified, so get data source's binding manager, and hook a 'related' binding manager to it
//
int lastDot = dataMember.LastIndexOf(".");
string dataPath = (lastDot == -1) ? "" : dataMember.Substring(0, lastDot);
string dataField = dataMember.Substring(lastDot + 1);
BindingManagerBase formerManager = EnsureListManager(dataSource, dataPath);
PropertyDescriptor prop = formerManager.GetItemProperties().Find(dataField, true);
if (prop == null)
throw new ArgumentException(SR.GetString(SR.RelatedListManagerChild, dataField));
if (typeof(IList).IsAssignableFrom(prop.PropertyType))
bindingManagerBase = new RelatedCurrencyManager(formerManager, dataField);
else
bindingManagerBase = new RelatedPropertyManager(formerManager, dataField);
}
My dataSource
is not an ICurrencyManagerProvider
What is the difference between these two calls, and why does accessing the PropertyManager
by only the dataSource
result in the bindings for another window with a separate BindingContext
being updated?
The BindingContext is aware of the first binding ( TextBox1 to Customers. FirstName ), so it would use the same CurrencyManager, as both text boxes are bound to the same dataset ( DataSet1 ). TextBox2.DataBindings.Add("Text", dataSet1, "Customers.LastName") C# Copy. textBox2.
A binding context is an object that holds data that you can reference from your bindings. While applying bindings, Knockout automatically creates and manages a hierarchy of binding contexts. The root level of the hierarchy refers to the viewModel parameter you supplied to ko. applyBindings(viewModel) .
You don't state this explicitly, so in case you haven't noticed it is the collection look up that is not working as you expect, because of the equal override.
BindingContext[datasource] is a lookup against the collection using datasource as the key.
BindingContext[datasource, datamember] is a lookup against the collection using a composite key.
It is clear from the code that BindingContext is maintaining two separate collections. One a collection on a datasource key and the other a collection based on a composite key.
Obviously your override of equal will twice place similar values to datasource in the BindingContext[datasource] collection, but will result in one collection entry, because the values/keys are the same. Whereas, it will place two entries in BindingContext[datasource, datamember].
If you inspect both collections and can get the counts you'll see that the later collection has more entries.
You have to remember that you have two separate objects that evaluate to equal, not two references to the same object. This is the crux of the problem.
It would appear that when adding the entries to the second collection (BindingContext[datasource, datamember]) datamember evaluates to unique.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With