2

どうやってそんなことをするのかしら。ツリーを変更するMVVMCRUDアプリがあるとします(たとえば、メニュー構造)。メニュー項目と2つのビューを備えたビューモデルがあります。1つ目はaTreeViewで、2つ目はDataForm。です。主な問題は次のとおりです。

  1. DataForm階層データを処理できません。
  2. で選択したメニュー項目に応じて、異なるフィールドのセットを表示TreeViewするDataForm 必要があります(たとえば、子のあるメニュー項目とないメニュー項目の場合)。

私は次のようになってしまいました。ビューモデルには3つのフィールドがあります。

  1. Items— 階層データソースを構築するためMenuItemの独自のコレクションを持つオブジェクトのコレクション。Children
  2. SelectedItem—現在。で選択さ MenuItemれていTreeViewます。
  3. EditedItemEditViewModel 基本的に2つの子孫を持つオブジェクト:MenuItemEditViewModelLeafMenuItemEditViewModel。このプロパティは、SelectedItemが変更されると自動的に設定されます。その実際のタイプは、 SelectedItem.Children空から推測されます。

TreeViewとにバインドされItemsSelectedItemいます。DataFormこの場合、通貨を維持する必要はありません(代わりに、現在のアイテムはによって設定されますTreeView)。また、アイテムの作成と削除を担当しません。そのため、CurrentItemモデルを表示するためにそれだけをバインドすることにしましたEditedItem(バインドされていませItemsSourceん)。AutoCommitに設定されていますFalse(バインドされていない場合、バインドTrueされていない場合、でItemsSource別のアイテムを選択すると、現在のすべてのアイテムの変更が新しく選択されたアイテムにコピーされますTreeView。これはあまり良くありません)。DataFormフィールドは自動生成されます。

明らかに、でアイテムを選択した場合、でTreeViewいくつかの変更を加えて、DataFormで別のアイテムを選択しようとすると、TreeViewよく知られるようになります。

アイテムに検証エラーがある場合、またはアイテムが編集中でAutoCommitがfalseの場合、通貨を変更できません。代わりにItemsSourceをICollectionViewに設定して、通貨を管理します

この場合DataForm、すべての変更を暗黙的に破棄します。選択したアイテムが変更さDataForm.CancelEdit()れる前に呼び出す回避策があります(通常はまたはのようなイベント)。ただし、とは完全に異なるビューで定義されているため、MVVMの方法ではありません(読み取り:は受け入れられません)。TreeViewPreviewSelectionChangedBeforeSelectionChangedTreeViewDataForm

DataForm変更されたときに変更を強制的にキャンセルするAutoCancelのようなものはありCurrentItemますか?たぶん、開発チームの誰かが答えることができますか?または、そのような問題にどのように対処しますか?

4

2 に答える 2

4

すべてのビジネス指向のRIA機能を考慮すると、Silverlightにこの機能が大幅に不足していることに驚きました。AutoCommitは、ユーザーが望まない可能性のあるものをデータベースにコミットするのではなく、保留中の変更を明示的に確認してほしいため、私には受け入れられません。

プライベートメンバー変数を使用し、DataFormのBeginningEditイベントとEditEndedイベントをトラップすることで、DataFormの編集モードを確実に追跡できます(名前の不一致!1つがxxxEditと呼ばれ、他がEditxxxと呼ばれる理由は私を超えています。EditBeginningとEditEndedではない場合??)。BeginningEditのイベントハンドラー内で、フラグをtrueに設定し、EditEndedでfalseに設定します。

次に、SelectionChangedイベントで、フラグを確認できます。trueの場合、DataFormでCancelEditを呼び出すことができます。

private bool _editing = false;

public MainPage() {
    DataForm1.BeinningEdit += 
        new EventHandler<CancelEventArgs>(DataForm1_BeginningEdit);
    DataForm1.EditEnded += 
        new EventHandler<DataFormEditEndedEventArgs>(DataForm1_EditEnded);
}

protected void DataForm1_BeginningEdit(object sender, 
    System.ComponentModel.CancelEventArgs e) {
    _editing = true;
}

protected void DataForm1_EditEnded(object sender, 
    DataFormEditEndedEventArgs e) {
    _editing = false;
}

void TreeView1_SelectedItemChanged(object sender, 
    RoutedPropertyChangedEventArgs<object> e)
{
    if (_editing) {
        object previous = DataForm1.SelectedItem;
        object current = TreeView1.SelectedItem;

        if (MessageBox.Show("Are you sure you want to cancel the changes?", 
            "Confirm", MessageBoxbutton.OKCancel) == MessageBoxResult.OK) {
            DataForm1.CancelEdit();
        }
        else {
            TreeView1.SelectedItem = previous;
        }
    }
}
于 2010-11-29T19:21:36.257 に答える
0

AutoCommit を True に設定しようとしましたか?

于 2010-10-22T15:01:25.230 に答える