2014-06-11 1 views
14

디버깅에 문제가있는 이상한 버그가 발생했습니다.왜 WinForms에서 .GetHashCode를 덮어 쓰면 이러한 데이터 바인딩 된 값이 지워 집니까?

Microsoft CAB, DevExpress 구성 요소 및 .Net 3.5를 사용하는 MDI 작업 영역이 있습니다.

사용자가 두 개의 개별 데이터 모델에 바인드 된 UserControl을 포함하는 두 개의 창을 열면 둘 다 최소화됩니다. 최소화 할 첫 번째 창은 두 번째 창이 최소화되면 바운드 필드가 지워집니다.

데이터 모델의 .Equals.GetHashCode 메소드가 오버라이드되어 두 데이터 모델이 동일하게 간주됩니다. 우리가 그것을 독특하게 바꾸면 우리는 이러한 행동을 취하지 않습니다.

enter image description here

위의 스택 추적에서 EndEditSession() 전화에서, 그것이 : 여기

var a = new MyWindow(); 
a.DataModel = new SomeClass(123); 
a.ShowInMdiWorkspace(); 

var b = new MyWindow(); 
b.DataModel = new SomeClass(123); 
b.ShowInMdiWorksace(); 

a.Minimize(); 

// If SomeClass.GetHashCode() is overwritten to consider two objects 
// as equal based on the value passed in, then the data bindings for A 
// get cleared on this call. If SomeClass.GetHashCode is unique, then 
// this problem does not happen. 
b.Minimize(); 

가 여기에 두 번째 창이 최소화됩니다 호출 스택의 문제를 보여주는 몇 가지 예를 들어 의사입니다 두 번째 창이 최소화 된 동안 EndEditSession을 호출하는 동안 스택 추적이 [External Code] 시간을 지나갈 때까지 내가 설정 한 OnChange 중단 점은 첫 번째 창에서 변경 메소드를 실행 중입니다.

EndEditSession()는 해당 UserControl은 데이터 바인딩을 초기화 할 때 채워 도착이

protected void EndEditSession() 
{ 
    IBindingValue bv = null; 

    if (_bindingValues == null) 
     return; 

    if (_data != null) 
    { 
     foreach (KeyValuePair<string, IBindingValue> kvp in _bindingValues) 
     { 
      bv = kvp.Value; 
      if (bv.IsBindable) 
       ((PropertyManager)bv.Component.BindingContext[_data]).EndCurrentEdit(); 
     } 
    } 

} 

_bindingValues과 같은 형태 우리가 구현 한 것이 정의입니다. 키 필드는 바운드 컨트롤의 이름이고 값 필드는 컨트롤 자체, 이름, 바운드 값 및 기본값을 저장하는 사용자 지정 개체입니다. bv.Component 내 시험의 경우 사용자 정의 DevExpress의 LookupEdit

_dataUserControl에 대한 데이터 모델을 포함 바인딩이에 설정되어 있는지 컨트롤을 반환하고, 나는 그것이 두 번째의 인스턴스로 설정되어 있는지 확인할 수 있습니다 창문.

내 원래의 생각은 BindingContext이 공유 되었기 때문에 잘못된 PropertyManager이 반환되었지만 두 양식과 컨트롤에 대한 .BindingContext은 별개임을 확인했습니다.

데이터 모델의 두 개의 별도 인스턴스에 바인드 된 UserControl의 두 개의 개별 사본을 사용하면 GetHashCode 메소드가 오버라이드되어 두 객체가 동일한 것으로 간주 될 때 바인딩이 섞일 수 있습니까?

WinForms 바인딩 시스템의 내부 동작이나 CAB의 MDI 작업 영역 관리 방식에 대해 잘 알고 있지 않습니다.

나의 이론은 첫 번째 창이 최소화되면 메모리를 절약하기 위해 컨트롤을 언로드 한 다음 두 번째 창이 바인딩을 관리하는 내부 해시 테이블을 최소화하면 잘못 혼동되어 데이터를 가져 오는 업데이트를 실행한다는 것입니다 첫 번째 최소화 된 창 (이제 비어 있음)과 해당 데이터 소스를 업데이트합니다.이 이론에는 많은 구멍이 있지만, 내가 생각할 수있는 유일한 것입니다.

답변

0

BindingContext 개체의 필드와 속성이 고정되어 있지 않으므로 BindingContext과 다른 필드와 속성을 공유하지 않습니다.

그러나 여러 개의 컨트롤에 하나의 BindingContext 개체를 사용할 수 있습니다.

첫 번째 경우 여러 컨트롤이 동일한 부모를 가지며 자체 컨트롤이없는 경우 BindingContext이 컨트롤의 BindingContext 속성은 Control.Parent(.Parent...).BindingContext 개체를 반환합니다. 세 번째 경우에 BindingContext

var bindingContext = new BindingContext(); 
var a = new SomeControl(); 
var b = new SomeControl(); 
a.BindingContext = bindingContext; 
b.BindingContext = bindingContext; 

하는 방식으로 덮어 쓰기 할 수 두번째 경우가있다에서

이 같을 수있다.

나는 당신의 경우에 무슨 일이 일어나고 있는지 모르는, 그래서는 초기화 데이터 바인딩하기 전에이 같은 뭔가를 추천 할 수 있습니다 :

var a = new SomeControl(); 
var b = new SomeControl(); 
a.BindingContext = new BindingContext(); 
b.BindingContext = new BindingContext(); 


을이 당신이 필요로하는 문제가 해결되지 않는 경우 _bindingValues 개체 채우기를 확인하십시오. 이 개체를 채우는 동안 잘못된 값으로 채워질 수 있습니다.

+0

그건 내 첫 번째 생각인데도, 각 컨트롤에 자신의 BindingContext를 할당 할 때 같은 문제가 여전히 발생합니다. – Rachel

+2

@Rachel 샘플 프로젝트를 제공 할 수 있습니까? 문제에 대한 정보가 충분하지 않은 것으로 보입니다. 나는 그 문제가'BindingContext'가 아니라고 생각한다. 문제는 당신의'_bindingValues' 객체에있을 수 있습니다. – nempoBu4

+0

샘플 프로젝트에서 실제로 재현 할 수 없었습니다. 샘플에 스마트 파트가 포함 된 전체 MDI 작업 영역을 작성하지 않았기 때문입니다. 내가 작업했던 샘플 코드는 TabControl, 사용자 지정 개체 및 사용자 지정 바인딩 코드가있는 사용자 지정 UserControl이있는 양식입니다. 오늘 다시 시도해보고 큰 샘플 프로젝트에서 문제를 재현 할 수 있는지 확인합니다. – Rachel

1

나는 내부 작업에게의 WinForm 위젯을 모른다, 그러나 당신이 를 오버라이드 (override)에 문제가 발생했습니다 때문에 당신이 주변에 작업 더 나을 거라고 같아 보인다.

당신이 당신의 자신의 목적을 위해 평등을 평가해야하는 경우 :

접근 방법이 아니라 기본 동작을 변경하는 대신, 평등을 평가하는 자신 만의 방법을 제공하는 것이다.

당신의 의도는 위젯이 개체를 처리하는 방법을 변경하는 경우 :

접근 방법이 클래스의 정적 객체 팩토리를 확인하는 것입니다. 팩토리는 약한 참조를 사용하여 생성 된 모든 객체의 컬렉션을 유지 관리 할 수 ​​있습니다. 약한 참조를 사용하면 GC가 객체를 수집 할 수 있습니다. 그런 다음 팩토리는 이전에 작성된 오브젝트의 콜렉션을 점검 할 수 있습니다. 일치하는 것이 있으면 기존 값을 리턴하십시오. 그렇지 않다면 생성하십시오. 이 방법은 2 개의 서로 다른 객체가 2 개의 동일한 객체 (equals를 오버라이드)를 갖는 것보다 두 개의 참조가 동일한 객체 (동일한 메모리)를 가질 수 있습니다.

이러한 다른 방법 중 하나를 사용하여 문제를 해결할 수 있기를 바랍니다.

관련 문제