1. ホーム
  2. c#

[解決済み】WPFツリービューのSelectedItemへのデータバインディング

2022-04-04 14:43:22

質問

WPF-treeviewで選択されている項目を取得するにはどうしたらよいですか?バインドしたいので、XAMLで行いたいのですが。

と思うかもしれませんが、それは SelectedItem が、どうやらその は存在しない はリードオンリーなので使えません。

これがやりたいことなんです。

<TreeView ItemsSource="{Binding Path=Model.Clusters}" 
            ItemTemplate="{StaticResource ClusterTemplate}"
            SelectedItem="{Binding Path=Model.SelectedCluster}" />

をバインドしたい。 SelectedItem をモデル上のプロパティに追加します。

しかし、これは私にエラーを与えます。

'SelectedItem' プロパティは読み取り専用で、マークアップから設定することはできません。

編集する OK、これは私がこれを解決した方法です。

<TreeView
          ItemsSource="{Binding Path=Model.Clusters}" 
          ItemTemplate="{StaticResource HoofdCLusterTemplate}"
          SelectedItemChanged="TreeView_OnSelectedItemChanged" />

と、私のxamlのcodebehindfileにあります。

private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    Model.SelectedCluster = (Cluster)e.NewValue;
}

解決方法は?

すでに回答が受け付けられているようですが、問題を解決するためにこれをまとめました。 これは、デルタの解決策と同様のアイデアを使用していますが、TreeViewをサブクラス化する必要はありません。

public class BindableSelectedItemBehavior : Behavior<TreeView>
{
    #region SelectedItem Property

    public object SelectedItem
    {
        get { return (object)GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));

    private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var item = e.NewValue as TreeViewItem;
        if (item != null)
        {
            item.SetValue(TreeViewItem.IsSelectedProperty, true);
        }
    }

    #endregion

    protected override void OnAttached()
    {
        base.OnAttached();

        this.AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        if (this.AssociatedObject != null)
        {
            this.AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
        }
    }

    private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        this.SelectedItem = e.NewValue;
    }
}

そして、これをXAMLで次のように使うことができます。

<TreeView>
    <e:Interaction.Behaviors>
        <behaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
    </e:Interaction.Behaviors>
</TreeView>

誰かの役に立てれば幸いです。