2

一種のスキーマを構成するモデル オブジェクトのツリーを持つアプリケーションがあります。これは次のようになります。

ElementSet
....ElementGroup
........ScalarElement
........BoolElement
....ElementGroup
........MatrixElement
........VectorElement

このツリーははるかに複雑ですが、アイデアは理解できます。このツリーを WPF TreeView に表示し、ユーザーが特定のノードを選択するだけでなく (マスター/詳細スタイル)、ノードを追加、削除、および再配置できるようにします。

私の意図は、ツリー内の各ノードを ViewModel にカプセル化することです。そこに、コマンド、ツールチップ情報、その他の ViewModel 関連の毛羽立ちを追加します。

私の問題は、モデルのツリーがあり、それに合わせてViewModelのツリーが本当に必要になるということです。これに対するエレガントな解決策を考えるのに苦労しています。これを構築するにはどうすればよいですか?それらを同期させますか?等

私がいじっているアイデアの 1 つは、View をモデル オブジェクトのグラフに直接バインドすることですが、ValueConverter を使用してモデルを各ノードの ViewModel に変換することです。各モデルには一意の ID があるため、コンバーターが ViewModel のクエリ可能なキャッシュを維持してビューに返すことは問題外ではありません。

モデルのコレクション/ツリーのビュー モデルを作成するために、他にどのような効果的な戦略が存在しますか?

4

2 に答える 2

1

ViewModelキャッシュでValueConverterを使用することになりました。それは実際には非常にうまく機能します。TreeView を次のように設定します。

<TreeView ItemsSource="{Binding TreeRoot}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <ContentPresenter Content="{Binding Converter={StaticResource ModelToViewModelConverter}}"/>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

...ここで、TreeRoot はモデル オブジェクトのツリーのルートであり、それぞれに "Children" プロパティがあります。そして、私のコンバーターを次のように作成しました:

public class ModelToViewModelConverter : IValueConverter
{
    private static Dictionary<Guid, ViewModelBase>  _map = new Dictionary<Guid, ViewModelBase>();

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var element = value as ElementBase;

        if (!_map.ContainsKey(element.Id))
        {
            if (element is ElementSet)_map.Add(element.Id, new ElementSetViewModel(value as ElementSet));
            if (element is ElementGroup) _map.Add(element.Id, new ElementGroupViewModel(value as ElementGroup));
            if (element is StringElement) _map.Add(element.Id, new StringElementViewModel(value as StringElement));
            if (element is ScalarElement) _map.Add(element.Id, new ScalarElementViewModel(value as ScalarElement));
        }

        return _map[element.Id];
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        //A change.sdfsdfdsff
        throw new NotImplementedException();
    }
}

これにより、Model オブジェクトのツリーを 1 つだけ維持できますが、View をバインドするために ViewModel を使用できます。

于 2013-10-24T06:58:46.760 に答える