2009-12-15 4 views
4

작은 응용 프로그램에서 Model-View-Controller 패턴을 사용하려고합니다. 모델에 다음과 같은 데이터가 포함되어 있습니다.Delphi에서 MVC의 순환 알림을 피하는 방법은 무엇입니까?

TModelSelection = record 
    CurrentItem : TItem; 
end; 

TModel = class 
public 
    property Items : TList <TItem>; 
    property Selection : TModelSelection; 
    property Subject : TSubject <TModel>; // Observer pattern 
end; 

이제 모델을 관찰하는 트리 뷰가 있습니다. 사용자가 트리 뷰에서 항목을 선택하면 모델 선택이 변경됩니다.

문제는 원형 변경 알림에 문제가 있다는 것입니다. 트리보기의 OnChange 이벤트에서 모델 선택을 변경합니다. 이로 인해 트리 뷰는 선택 사항을 업데이트합니다 (선택 사항은 응용 프로그램의 다른 부분에서도 변경 될 수 있기 때문에). 그러면 OnChange 이벤트가 다시 트리거됩니다.

이 문제를 어떻게 피할 수 있습니까?

답변

9

은 실제 변경 사항에 대해서만 통지합니다.

업데이트 중에는 플래그를 사용하여 업데이트를 사용하지 않도록 설정하십시오. 그것은 단순히 모델을 반영 않을 때 뷰의 변화 모델에 영향을 미칠 않습니다 - FChanging가

+1

+1 감사합니다. 플래그를 사용하면 나를 위해 그것을 않습니다. – jpfollenius

+0

내가 도울 수있어서 기쁩니다. 이 패턴을 본 후에는 매우 분명합니다. 그것은 종종 도움이됩니다. –

+0

나쁘지는 않지만 ... 그렇지 않다면 FChanging 다음 FChanging 시도 : = TRUE; ... 마침내 FChanging : = FALSE; 끝 : "나에게 더 나은 것 :-) – JensG

8

MVC와 고전적인 문제 부울 타입의 멤버 변수 인과

procedure OnChange(...) 
begin 
    if FChanging = false then 
    begin 
    FChanging:=true; 
    ... do updates 
    FChanging:=false; 
    end; 
end; 

?

이것은 컨트롤러에서 처리해야합니다. 컨트롤러에서 처리하지 않으면 MVC 구현이 아니라 컨트롤러 로직이 포함 된 MV 만 모델 및 모델 간의 상호 작용 전반에 분산됩니다. 보기.

사용자가보기 (트리보기 컨트롤)와 상호 작용하면 컨트롤러에 모델을 업데이트해야합니다.

모델이 업데이트되면 컨트롤러에 알려야합니다.

이 시나리오에서 컨트롤러는 모델을 업데이트한다는 것을 컨트롤러가 이미 알고 있으므로 그렇지 않으면보기로 전달할 특정 알림을 무시할 수 있습니다.

가장 큰 문제는 뷰에 사용 된 컨트롤이 MVC 구현에서 사용하기에 이상적이라고 생각하는 것입니다. 트리 뷰를 클릭하면 트리 뷰 컨트롤 (보기) 자체의 선택이 변경됩니다. MVC에서 이상적으로 원하는 것은 클릭 한 항목으로 선택 항목을 변경해야한다는 것을 컨트롤러를 통해 모델에 알리는 것입니다.

따라서 모델 선택 상태가 변경되고 트 리뷰에 통지됩니다. 뷰는 모델에 대해 현재 무엇을하는지 이미 알고 있다고 가정해서는 안됩니다.

Treeview 선택 상태는 항상 모델 상태를 반영합니다.

그러나 사용자 인터페이스 컨트롤에서 일부 작업을 수행하지 않고도 컨트롤 상태와 기본 모델 상태 사이에이 거리를 만들지 않고도 작업 해결 방법으로 어려움을 겪어야합니다.

+0

+1 설명을 주셔서 감사합니다. 나는 이것이 깨끗한 MVC 솔루션이 아니며 Delphi에서의 깨끗한 솔루션은 아마도 많은 작업을 의미한다는 것을 알게되었습니다 ... – jpfollenius

0

현재 선택 영역을보기 레이어 (예 : 현재 선택된 노드)에 저장합니다. 컨트롤러가 새 노드로 전환하고이 노드를 이미 선택했는지 묻는 메시지가 표시되면 아무 것도하지 않습니다.

속성을 설정 델파이 구성 요소의

표준 동작 : 토비아스 LANGNER 좋은하지 않음으로써 "상태 변경"과

type TSomeClass = class 
    private 
    FSomeValue : TSomeType; 
    protected 
    procedure SetSomeProperety(const AValue: TSomeType); 
    public 
    property SomeProperty : TSomeType read FValue write SetSomeProperty; 
end; 

procedure TSomeClass.SetSomeProperety(const AValue: TSomeType); 
begin 
    if(AValue = FValue) then exit; 
    FValue := AValue; 
    // do other actions to reflect change 
end; 

웨이 - 컨트롤러는 다른 노드를 선택하기로 결정, 적어도이 필요할 수 있습니다

try 
    ... 
finally 
    FChanging := false; 
end; 

블록.

관련 문제