必要に応じて、添付プロパティと外部依存関係なしで回答してください!
バインド可能でゲッターとセッターを持つ添付プロパティを作成できます。
public class TreeViewHelper
{
private static Dictionary<DependencyObject, TreeViewSelectedItemBehavior> behaviors = new Dictionary<DependencyObject, TreeViewSelectedItemBehavior>();
public static object GetSelectedItem(DependencyObject obj)
{
return (object)obj.GetValue(SelectedItemProperty);
}
public static void SetSelectedItem(DependencyObject obj, object value)
{
obj.SetValue(SelectedItemProperty, value);
}
// Using a DependencyProperty as the backing store for SelectedItem. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.RegisterAttached("SelectedItem", typeof(object), typeof(TreeViewHelper), new UIPropertyMetadata(null, SelectedItemChanged));
private static void SelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is TreeView))
return;
if (!behaviors.ContainsKey(obj))
behaviors.Add(obj, new TreeViewSelectedItemBehavior(obj as TreeView));
TreeViewSelectedItemBehavior view = behaviors[obj];
view.ChangeSelectedItem(e.NewValue);
}
private class TreeViewSelectedItemBehavior
{
TreeView view;
public TreeViewSelectedItemBehavior(TreeView view)
{
this.view = view;
view.SelectedItemChanged += (sender, e) => SetSelectedItem(view, e.NewValue);
}
internal void ChangeSelectedItem(object p)
{
TreeViewItem item = (TreeViewItem)view.ItemContainerGenerator.ContainerFromItem(p);
item.IsSelected = true;
}
}
}
そのクラスを含む名前空間宣言をXAMLに追加し、次のようにバインドします(ローカルは名前空間宣言に名前を付けた方法です)。
<TreeView ItemsSource="{Binding Path=Root.Children}" local:TreeViewHelper.SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}">
</TreeView>
これで、選択したアイテムをバインドし、ビューモデルに設定して、要件が発生した場合にプログラムで変更できるようになりました。もちろん、これは特定のプロパティにINotifyPropertyChangedを実装することを前提としています。