3

かなり標準的な要件があります。ユーザーがデータ バインド フィールドの値を変更できるダイアログを開き、[OK] または [キャンセル] をクリックすることを選択できるようにする必要があります。[キャンセル] をクリックすると、変更が元に戻ります。

IEditableCollectionViewIEditableObjectおよびを見てきましたBindingGroupが、それらはすべて一度に 1 つの項目を編集するためのもののようです。私のプログラムはリスト内のオブジェクトのコレクションを提供し、ユーザーはリストからアイテムを選択し、SelectedItem-bound TextBoxes を使用して編集します。つまり、リストへの追加やリストからの削除を含め、任意の数のアイテムを編集できます。キャンセルを押すと、これらの変更はすべて元に戻す必要があります。

最初は、単純にディープ コピー (シリアライゼーション) によってオブジェクトのバックアップを作成し、キャンセル時にそれらを復元していましたが、現在ではオブジェクトに他の共有オブジェクトへの参照が含まれている必要があり、このアプローチが問題になっています。

オブジェクトや値を手動でコピーせずに、このようなシナリオにアプローチする最善の方法は何ですか?

4

3 に答える 3

1

この場合、DataTableクラスは完全に機能します。変更を保存したり、(ステップごとに) 戻ったり、すべての変更やその他の多くの機能を元に戻したりできます。DataTable クラスには、XML に適した入れ子機能があります。

データベースに保存する場合は、EntityFrameworkをご覧ください。

于 2013-01-20T16:13:31.763 に答える
0

この問題についてさらに考えた結果、少なくとも小規模な実装では、オブジェクト自体を置き換えることなくオブジェクトのフィールドとプロパティの値をコピーする「値によるディープ コピー」メソッドを作成することが最善の方法であるという結論に達しました (そのため、編集されたオブジェクトへの参照は、データが復元されてもそのまま残ります)。

この目的のために、次の拡張メソッドを作成しました。

public static void CopyDataTo(this Object source, Object target) {
    // Recurse into lists
    if (source is IList) {
        var a = 0;
        foreach (var item in (IList)source) {
            if (a >= ((IList)target).Count) {
                var type = item.GetType();
                var assembly = Assembly.GetAssembly(type);
                var newItem = assembly.CreateInstance(type.FullName);
                ((IList)target).Add(newItem);
            }
            item.CopyDataTo(((IList)target)[a]);
            a++;
        }
        while (a < ((IList)target).Count) {
            ((IList)target).RemoveAt(a);
        }
    }

    // Copy over fields
    foreach (var field in source.GetType().GetFields())
        field.SetValue(target, field.GetValue(source));
    // Copy properties
    foreach (var property in source.GetType().GetProperties().Where(
        property => property.CanWrite && !property.GetMethod.GetParameters().Any()))
    {
        property.SetValue(target, property.GetValue(source));
    }
}

これは特効薬ではありません。同じ型のオブジェクトでのみ機能し、リスト項目にはパラメーターのないコンストラクターが必要であり、再帰の深さを制御する方法はありません。さらに、長期的またはより複雑なシナリオでテストする機会はまだありませんが、これまでのところ、必要なこと (オブジェクト間で値をコピーする) を行い、単純なバックアップ/復元シナリオに使用できます。

var backup = new TypeOfVariableToEdit();
data.CopyDataTo(backup);
var clickedOK = RunDataEditor(data);
if (!clickedOK)
    backup.CopyDataTo(data);
于 2013-01-20T16:58:42.247 に答える
-1

最良のアプローチは、次のことではありません。

これらの項目が必要な場合は、データベースまたはその他のデータ ストレージからそれらの新しいコピーを取得し、ユーザーが変更できるようにし、ユーザーがキャンセルを押した場合は変更を破棄します。保存を押した場合は、データをストレージに保存してから、既存の画面などを更新します。

于 2013-01-20T16:34:53.413 に答える