概要
これは、TreeView の選択された項目のプロパティをソース上の何かにバインドするという単純な問題です。ただし、TreeView コントロールの作成方法が原因で、すぐに使用できる WPF を使用して MVVM に適したソリューションを取得するには、より多くのコードを記述する必要があります。
バニラの WPF を使用している場合 (そうであると想定しています)、アタッチされたビヘイビアーを使用することをお勧めします。添付された動作は、TreeView の選択が変更されたときに呼び出されるメイン ビュー モデルのアクションにバインドされます。アクションの代わりにコマンドを呼び出すこともできますが、ここではアクションの使用方法を示します。
基本的に、全体的な考え方は、マスター ビュー モデルのプロパティとして使用できるようになる詳細ビュー モデルの 1 つのインスタンスを使用することです。次に、何百ものビュー モデルのインスタンスを持つ RootItems コレクションの代わりに、ノードの表示名とおそらくその背後にある種の id フィールドを持つ軽量オブジェクトを使用できます。TreeView の選択が変更されたら、メソッドを呼び出すか、プロパティを設定して、詳細ビュー モデルに通知する必要があります。以下のデモ コードでは、Selection という DetailsViewModel のプロパティを設定しています。
コードによるウォークスルー
添付された動作のコードは次のとおりです。
public static class TreeViewBehavior
{
public static readonly DependencyProperty SelectionChangedActionProperty =
DependencyProperty.RegisterAttached("SelectionChangedAction", typeof (Action<object>), typeof (TreeViewBehavior), new PropertyMetadata(default(Action), OnSelectionChangedActionChanged));
private static void OnSelectionChangedActionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var treeView = sender as TreeView;
if (treeView == null) return;
var action = GetSelectionChangedAction(treeView);
if (action != null)
{
// Remove the next line if you don't want to invoke immediately.
InvokeSelectionChangedAction(treeView);
treeView.SelectedItemChanged += TreeViewOnSelectedItemChanged;
}
else
{
treeView.SelectedItemChanged -= TreeViewOnSelectedItemChanged;
}
}
private static void TreeViewOnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var treeView = sender as TreeView;
if (treeView == null) return;
InvokeSelectionChangedAction(treeView);
}
private static void InvokeSelectionChangedAction(TreeView treeView)
{
var action = GetSelectionChangedAction(treeView);
if (action == null) return;
var selectedItem = treeView.GetValue(TreeView.SelectedItemProperty);
action(selectedItem);
}
public static void SetSelectionChangedAction(TreeView treeView, Action<object> value)
{
treeView.SetValue(SelectionChangedActionProperty, value);
}
public static Action<object> GetSelectionChangedAction(TreeView treeView)
{
return (Action<object>) treeView.GetValue(SelectionChangedActionProperty);
}
}
次に、TreeView 要素の XAML で、次を適用しますlocal:TreeViewBehavior.SelectionChangedAction="{Binding Path=SelectionChangedAction}"
。TreeViewBehavior
クラスの名前空間を local に置き換える必要があることに注意してください。
ここで、次のプロパティを MainWindowViewModel に追加します。
public Action<object> SelectionChangedAction { get; private set; }
public DetailsViewModel DetailsViewModel { get; private set; }
MainWindowViewModel のコンストラクターで、SelectionChangedAction プロパティを何かに設定する必要があります。SelectionChangedAction = item => DetailsViewModel.Selection = item;
DetailsViewModel に Selection プロパティがある場合は、そうすることができます。それは完全にあなた次第です。
最後に、XAML で、次のように詳細ビューをそのビュー モデルに結び付けます。
<View:ItemDetails DataContext="{Binding Path=DetailsViewModel}" />
これは、ストレート WPF を使用した MVVM フレンドリー ソリューションの基本アーキテクチャです。そうは言っても、Caliburn.Micro や PRISM などのフレームワークを使用している場合、アプローチはおそらくここで提供したものとは異なるでしょう。それを覚えておいてください。