我们遇到了problem
.Equals
和.GetHashCode
方法重写为等同。.EndCurrentEdit()
会触发Window 1 BindingContext
我们发现问题与调用
有关((PropertyManager)ctrl.BindingContext[dataSource]).EndCurrentEdit();
如果我们将其更改为
((PropertyManager)ctrl.BindingContext[dataSource, dataMember]).EndCurrentEdit();
它正常工作。如果我们删除.Equals
和.GetHashCode
覆盖,它也可以正常工作,因此两个对象模型不再被视为相等。
这对我没有意义,因为窗口是相同的,所以dataMember
属性也是一样的。
从this link开始,我相信这些电话的定义是:
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);
}
我的dataSource
不是ICurrencyManagerProvider
这两个调用之间有什么区别,为什么只有PropertyManager
访问dataSource
导致另一个窗口的绑定更新了单独的BindingContext
?
答案 0 :(得分:1)
你没有明确说明这一点,所以万一你没有注意到集合查找不能按预期工作,因为等于覆盖。
BindingContext [datasource] 是使用数据源作为键对集合进行查找。
BindingContext [datasource,datamember] 是使用复合键对集合进行查找。
从代码中可以清楚地看出 BindingContext 正在维护两个单独的集合。一个是数据源密钥的集合,另一个是基于组合密钥的集合。
显然,你的覆盖等于将两次将相似的值放在BindingContext [datasource]集合中的数据源中,但是会产生一个集合条目,因为值/键是相同的。然而,它将在BindingContext [datasource,datamember]中放置两个条目。
如果您检查两个集合并且可以获得计数,您会看到后面的集合有更多条目。
您必须记住,您有两个单独的对象,它们评估为相同,而不是两个对同一对象的引用。这是问题的症结所在。
当将条目添加到第二个集合(BindingContext [datasource,datamember])时,似乎数据集评估为唯一。
答案 1 :(得分:0)
访问BindingContext[dataSource]
时,实际访问BindingContext[dataSource, ""]
。因此,除了使用DataSource
和DataMember
值进行计算的HashCode之外没有区别,可以在link中看到。
public override int GetHashCode() {
return dataSourceHashCode * dataMember.GetHashCode();
}
单独的BindingContext
对象中的问题可能是它们未正确填充。