2014-06-12 16 views
12

Chúng tôi đã chạy vào một problem nơiĐiều gì khác biệt khi truy cập BindingContext [dataSource] và BindingContext [dataSource, dataMember]?

  • Chúng tôi có hai trường hợp cùng một cửa sổ trong một không gian làm việc MDI ràng buộc để hai mô hình đối tượng riêng biệt.
  • Mô hình đối tượng có các phương thức .Equals.GetHashCode được ghi đè để được xem là bằng nhau.
  • Calling .EndCurrentEdit() trên cửa sổ 2 được kích hoạt một bản cập nhật bắt buộc đối với Window 1
  • Cả hai cửa sổ được thiết lập để sử dụng riêng một BindingContext

Chúng tôi đã phát hiện ra vấn đề đã làm với gọi

((PropertyManager)ctrl.BindingContext[dataSource]).EndCurrentEdit(); 

Nếu chúng tôi thay đổi điều đó thành

((PropertyManager)ctrl.BindingContext[dataSource, dataMember]).EndCurrentEdit(); 

Nó hoạt động chính xác. Nó cũng hoạt động chính xác nếu chúng tôi xóa các ghi đè .Equals.GetHashCode của chúng tôi để hai mô hình đối tượng không còn được coi là bằng nhau nữa.

Điều đó không có ý nghĩa với tôi vì các cửa sổ giống nhau, vì vậy thuộc tính dataMember cũng sẽ giống nhau.

Từ this link, tôi tin rằng định nghĩa của các cuộc gọi là:

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 không phải là một ICurrencyManagerProvider

sự khác biệt giữa hai cuộc gọi này là gì, và tại sao không truy cập vào PropertyManager chỉ các kết quả dataSource trong các ràng buộc cho một cửa sổ khác với BindingContext riêng biệt đang được cập nhật?

+0

Đó là một sự xấu hổ không ai đã cân nhắc về vấn đề này, tôi tìm thấy câu hỏi hấp dẫn. – DonBoitnott

Trả lời

0

Khi bạn truy cập BindingContext[dataSource], bạn thực sự truy cập BindingContext[dataSource, ""]. Vì vậy, không có sự khác biệt ngoại trừ HashCode, sử dụng cả hai giá trị DataSourceDataMember để tính toán, có thể được nhìn thấy trong link của bạn.

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

Các vấn đề trong riêng biệt BindingContext các đối tượng có thể không được điền chính xác.

1

Bạn không nêu này một cách rõ ràng, vì vậy trong trường hợp bạn chưa nhận thấy nó là bộ sưu tập nhìn lên không hoạt động như mong đợi, vì bằng ghi đè.

BindingContext [datasource] là tra cứu bộ sưu tập bằng cách sử dụng nguồn dữ liệu làm khóa.

BindingContext [datasource, datamember] là tra cứu bộ sưu tập sử dụng khóa tổng hợp.

Rõ ràng từ mã rằng BindingContext đang duy trì hai bộ sưu tập riêng biệt. Một bộ sưu tập trên khóa nguồn dữ liệu và bộ sưu tập khác dựa trên khóa tổng hợp .

Rõ ràng việc ghi đè lên bằng nhau hai lần sẽ đặt các giá trị tương tự vào nguồn dữ liệu trong bộ sưu tập BindingContext [datasource], nhưng sẽ dẫn đến một mục nhập bộ sưu tập vì các giá trị/khóa giống nhau. Trong khi đó, nó sẽ đặt hai mục trong BindingContext [datasource, datamember].

Nếu bạn kiểm tra cả hai bộ sưu tập và có thể nhận số đếm bạn sẽ thấy rằng bộ sưu tập sau có mục nhập khác.

Bạn phải nhớ rằng bạn có hai đối tượng riêng biệt đánh giá bằng nhau, không phải là hai tham chiếu đến cùng một đối tượng. Đây là mấu chốt của vấn đề.

Có vẻ như khi thêm các mục vào bộ sưu tập thứ hai (BindingContext [datasource, datamember]), dữ liệu đánh giá là duy nhất.

+1

Để nói đơn giản: Ghi đè bằng của bạn sẽ trả về true mặc dù chúng không thực sự là các đối tượng bằng nhau. – pashute

Các vấn đề liên quan