Чем отличается доступ к BindingContext [dataSource] и BindingContext [dataSource, dataMember]?
Мы столкнулись с проблемой , где
- У нас есть два экземпляра одного окна в рабочей области MDI, связанное с двумя отдельными объектными моделями.
- Объектные модели имеют свои методы
.Equals
и .GetHashCode
, которые считаются равными.
- Вызов
.EndCurrentEdit()
в окне 2 запускает обновление привязки для окна 1
- Оба окна настроены на использование отдельных
BindingContext
Мы обнаружили, что проблема связана с вызовом
((PropertyManager)ctrl.BindingContext[dataSource]).EndCurrentEdit();
Если мы изменим это на
((PropertyManager)ctrl.BindingContext[dataSource, dataMember]).EndCurrentEdit();
Он работает правильно. Он также работает правильно, если мы удалим наши переопределения .Equals
и .GetHashCode
, поэтому две объектные модели больше не считаются равными.
Это не имеет смысла для меня, потому что окна одинаковы, поэтому свойство dataMember
будет таким же.
От эта ссылка, я считаю, что определение этих вызовов:
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 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
не является ICurrencyManagerProvider
В чем разница между этими двумя вызовами и почему доступ к PropertyManager
только с помощью dataSource
приводит к привязкам для другого окна с обновляемым отдельным BindingContext
?
Ответы
Ответ 1
Вы не указали это явно, поэтому, если вы не заметили, что это поиск коллекции, который не работает так, как вы ожидаете, из-за equal переопределить.
BindingContext [datasource] - это поиск по коллекции с использованием источника данных в качестве ключа.
BindingContext [datasource, datamember] - это поиск по коллекции с использованием составного ключа.
Из кода видно, что BindingContext поддерживает две отдельные коллекции. Одна коллекция с ключом datasource, а другая - на основе составного ключа.
Очевидно, что ваше переопределение равных будет дважды помещать аналогичные значения в источник данных в коллекции BindingContext [datasource], но приведет к одной записи коллекции, поскольку значения/ключи одинаковы. Принимая во внимание, что в BindingContext [datasource, datamember] будут помещены две записи.
Если вы проверите обе коллекции и получите количество, вы увидите, что в более поздней коллекции больше записей.
Вы должны помнить, что у вас есть два отдельных объекта, которые оцениваются равными, а не две ссылки на один и тот же объект. В этом суть проблемы.
Похоже, что при добавлении записей во второй набор (BindingContext [datasource, datamember]) datamember оценивается как уникальный.
Ответ 2
При обращении к BindingContext[dataSource]
вы фактически получаете доступ к BindingContext[dataSource, ""]
. Таким образом, нет никакой разницы, кроме HashCode, которая использует значения DataSource
и DataMember
для расчета, которые можно увидеть в вашей .
public override int GetHashCode() {
return dataSourceHashCode * dataMember.GetHashCode();
}
Проблема в отдельных объектах BindingContext
может заключаться в том, что они не заполнены правильно.