访问 BindingContext[dataSource] 和 BindingContext[dataSource, dataMember] 有什么不同?

13

我们遇到了一个问题,其中:

  • 在一个 MDI 工作区中,我们有两个实例绑定到两个不同的对象模型。
  • 这些对象模型已覆盖其 .Equals.GetHashCode 方法以被认为是相等的。
  • 在窗口2上调用 .EndCurrentEdit() 会触发窗口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'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

这两个调用有什么区别,为什么仅通过dataSource访问PropertyManager会导致绑定到另一个具有独立BindingContext的窗口的数据更新?


很遗憾没有人对这个问题发表意见,我觉得这个问题很有趣。 - DonBoitnott
2个回答

1

您没有明确说明,因此如果您没有注意到,那么可能是因为集合查找未按照您的预期工作,这是由于等号重写引起的。

BindingContext [datasource] 是使用 datasource 作为键 对集合进行查找。

BindingContext [datasource, datamember] 是使用组合键对集合进行查找。

从代码中可以清楚地看出,BindingContext维护着两个独立的集合。一个是基于数据源键的集合,另一个是基于组合键的集合。

显然,您对等号的重写将使类似于数据源的值在BindingContext[datasource]集合中出现两次,但只会导致一个集合条目,因为这些值/键是相同的。而它将在 BindingContext[datasource, datamember] 中放置两个条目。

如果您检查两个集合并获取计数,您会发现后者的条目更多

你必须记住,你有两个不同的对象被评估为相等,而不是指向同一对象的两个引用。这是问题的核心。
添加条目到第二个集合(BindingContext[datasource, datamember])时,datamember 看起来是唯一的。

1
简单来说:你的等于重写方法返回了 true,尽管它们实际上并不是相等的对象。 - pashute

0

当你访问 BindingContext[dataSource] 时,实际上你访问的是 BindingContext[dataSource, ""]。因此,除了哈希码之外,没有任何区别,哈希码使用 DataSourceDataMember 值进行计算,这可以在你的 链接 中看到。

public override int GetHashCode() {
    return dataSourceHashCode * dataMember.GetHashCode();
}

BindingContext 对象分开使用的问题在于它们可能没有被正确填充。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接