如何在Delphi的MVC中避免循环通知?

jpf*_*ius 4 delphi model-view-controller design-patterns

我试图在一个小应用程序中使用模型 - 视图 - 控制器模式.该模型包含一些数据和这样的选择

TModelSelection = record
  CurrentItem : TItem;
end;  

TModel = class
public
  property Items : TList <TItem>;
  property Selection : TModelSelection;
  property Subject : TSubject <TModel>;    // Observer pattern
end;
Run Code Online (Sandbox Code Playgroud)

现在我有一个观察模型的树视图.如果用户在树视图中选择项目,则模型选择应该更改.

问题是我遇到了循环更改通知的问题:我在树视图的OnChange事件中更改了模型选择.这会导致树视图更新其选择(因为选择也可以由应用程序的其他部分更改),这会再次触发OnChange事件,依此类推.

我该如何避免这个问题?

Tob*_*ner 9

仅通知真实的变化.

或者使用标志在更新期间禁用更新.

procedure OnChange(...)
begin
  if FChanging = false then
  begin
    FChanging:=true;
    ... do updates
    FChanging:=false;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

FChanging是Boolean类型的成员变量


Del*_*ics 8

MVC的一个典型问题 - 视图中的更改何时影响模型,何时仅反映模型?

这应该由控制器来处理 - 如果控制器没有处理它,那么你实际上没有MVC实现,而只是一个MV,其中嵌入了控制器逻辑并分布在模型和视图之间的交互中.

当用户与View视图(树视图控件)交互时,应通知Controller,后者又会更新模型.

更新模型时,应通知Controller.

在这种情况下,Controller已经意识到它正在更新模型,因此可以忽略它传递给View的某些通知.

您面临的最大问题是View中使用的控件并非理想地设计用于MVC实现.单击树视图会更改树视图控件(视图)本身中的选择.理想情况下,在MVC中,您希望它做的是通知模型(通过Controller)需要将选择更改为单击的项目.

因此,模型选择状态发生变化,并通知Treeview.No View应该假设它已经知道它对模型做了什么.

树视图选择状态始终只是模型状态的反映.

但是,如果没有在用户界面控件中做一些工作来在控制状态和底层模型状态之间创建这个距离,那么您将不得不努力解决问题.