オブジェクトの編集と isDirty() フラグ
-
03-07-2019 - |
質問
私は、ユーザーが GUI を通じて既存のオブジェクト (正確には「フィルター」ドメイン オブジェクト) を編集できるシステムに取り組んでいます。UI のヒントとして、ユーザーが実際にオブジェクトに何かを変更した場合にのみ保存ボタンを有効にします。この問題を経験したことがある人はいるだろうか、そしてこれに対処する最善の方法は何だろうかと考えていました。
isDirty() フラグをドメイン オブジェクトに追加することを考えていました。ユーザーがフィルターの編集を開始したら、コピーを作成して GUI に渡し、ユーザーがそのコピーを変更できるようにします。isDirty() フラグのバインディングにより、保存ボタンが有効または無効になります。保存すると、差異は元のオブジェクトにマージされ、永続化されます。
さらに、ユーザーがオブジェクトに加えた変更を元に戻した場合に何が起こるか考えていました。isDirty() フラグは false を返すはずです。したがって、これを達成する唯一の方法は、ドメイン オブジェクト内の各プロパティの元の値を保持することだと思います。
何か案は?
解決
正しい!
さらに、次の 2 つのメソッドを公開できます。BeginEdit - このメソッドでは、IsDirty フラグを True にマークします。つまり改造を行っているということです。変更を加えようとしているときにこのメソッドを呼び出します
CancelEdit - このメソッドでは、IsDirty フラグを False にリセットします。これは、編集プロセスを中止し、元の状態に戻したことを意味します。変更をキャンセルする場合は、このメソッドを呼び出します。
また、変更が永続化されたら、IsDirty フラグも False にリセットします。
これがお役に立てば幸いです。
他のヒント
.NET Framework を使用している場合は、Rockford Lhotka による CSLA .NET Framework を参照してください。 http://www.lhotka.net/cslanet/Default.aspx
CSLA は、オブジェクト状態管理 (IsDirty)、元に戻す機能、データ バインディングなどを含む成熟したフレームワークであり、さらに無料でオープンソースです。
変更の追跡と元に戻すのに役立つインターフェイスがいくつか実装できます。INotifyPropertyChanged と IEditableObject。これらのインターフェイスの両方を使用すると、オブジェクトがデータバインディングを適切に処理できるようになります。
public class Person : INotifyPropertyChanged, IEditableObject
{
private bool isDirty;
public bool IsDirty
{
get { return isDirty; }
}
private string firstname = string.Empty;
public string Firstname
{
get { return firstname; }
set
{
if (firstname == value) return;
firstname = value;
NotifyPropertyChanged("Firstname");
}
}
private string lastname = string.Empty;
public string Lastname
{
get { return lastname; }
set
{
if (lastname == value) return;
lastname = value;
NotifyPropertyChanged("Lastname");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
isDirty = true;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private bool inTrans;
private Person copy;
public void BeginEdit()
{
if (!inTrans)
{
if (copy == null)
copy = new Person();
copy.isDirty = isDirty;
copy.Firstname = Firstname;
copy.Lastname = Lastname;
inTrans = true;
isDirty = false;
}
}
public void CancelEdit()
{
if (inTrans)
{
isDirty = copy.isDirty;
Firstname = copy.Firstname;
Lastname = copy.Lastname;
inTrans = false;
}
}
public void EndEdit()
{
if (inTrans)
{
copy = null;
inTrans = false;
}
}
}
編集中のオブジェクトのセットがある場合は、おそらく isDirty() のブール フラグ以上のものが必要になります。この問題は参照カウントと似ています。編集時にダーティ カウントをインクリメントし、アンドゥ時にデクリメントします。undo をサポートしている場合は、かなり厄介なロジックになるのではないかと思います。ドメインオブジェクトからは外しておきたいと思います。
はい、これはうまくいきます。元に戻すのではなく、IsDirty メソッドを使用して、何かがレコードを変更した可能性があることを示し、それによって「レコードが変更されたかどうか」ロジックがトリガーされます。私は独自のフレームワークを開発しました。このフレームワークでは、すべてのテーブル フィールドが実際にはオブジェクトのプロパティになります。フィールドがオブジェクトに書き込まれるたびに、「isDirty」フラグが設定されます。オブジェクトの「SaveObject」メソッド (実際にはヘルパー クラスですが、簡単にオブジェクト内に含めることができますが、XML、データベースなど、さまざまな方法でオブジェクトを保存する機能が必要でした) で、IsDirty とfalse の場合は保存をスキップします。これにより、オブジェクトを変更する可能性があるたびに SaveObject を呼び出してフレームワークに処理させるため、ロジックが簡素化されます。
ドメインによっては、等価性を使用して差異をテストできます。元のオブジェクトを保持し、編集用にオブジェクトのコピーを作成します。編集を実行する場合は、UI を適切に変更してください。
この提案の利点は、ドメイン オブジェクトに GUI 固有の機能 (isDirty() フラグ) を固定しないことですが、YMMV
「最後の保存以降のすべてを元に戻す」よりも高い粒度レベルで操作の取り消しをサポートしている場合は、元に戻すスタックをお勧めします。何かが編集されると、それ (または元に戻す操作ファンクターまたはデリゲート) がスタックに追加されます。元に戻す場合は、スタックをポップし、ポップされた操作を元に戻すだけです。isDirty() フラグは、更新する追加のストレージやロジックではなく、元に戻すスタックに項目が含まれているかどうかをチェックするだけです。