c# - TreeView SelectedItem 行为 - 双向绑定(bind)在一个方向上不起作用

标签 c# wpf xaml treeview behavior

我创建了一个非常简单的示例来说明我的问题。也许我只是想错了。

我想从我的 TreeView 中选择一个项目 - 我想在 View (蓝色背景)中看到它。

为了实现 TwoWayBinding,我使用了这个行为:Data binding to SelectedItem in a WPF 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;
    }
}

但如果我点击一个项目,它不会进入 OnSelectedItemChanged 的“if”,因为 e.newValue as TreeViewItemnull

我的 XAML 非常简单:

<StackPanel>
    <TreeView xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
      ItemsSource="{Binding Items}">
        <i:Interaction.Behaviors>
            <local:BindableSelectedItemBehavior
                SelectedItem="{Binding Item}" />
        </i:Interaction.Behaviors>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate>
                <TextBlock Text="{Binding Text}"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
    <TextBox Text="{Binding Item.Text}"/>
</StackPanel>

谢谢大家!

最佳答案

为了方便起见,这里是结合OP 的最终解决方案和 ghrod's answer :

namespace MyPoject.Behaviors
{
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Interactivity;

  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(
          nameof(SelectedItem),
          typeof(object),
          typeof(BindableSelectedItemBehavior),
          new FrameworkPropertyMetadata(null, 
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
            OnSelectedItemChanged));

    static void OnSelectedItemChanged(DependencyObject sender, 
      DependencyPropertyChangedEventArgs e)
    {
      var behavior = (BindableSelectedItemBehavior)sender;
      var generator = behavior.AssociatedObject.ItemContainerGenerator;
      if (generator.ContainerFromItem(e.NewValue) is TreeViewItem item)
        item.SetValue(TreeViewItem.IsSelectedProperty, true);
    }
    #endregion

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

      AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
    }

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

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

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

关于c# - TreeView SelectedItem 行为 - 双向绑定(bind)在一个方向上不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31988038/

相关文章:

c# - 将 YYYYMMDD 字符串转换为 MM/DD/YYYY 字符串

c# - 在 ASP.NET Web API 中抑制 JsonMediaTypeFormatter 的 RequiredAttribute 验证

c# - 寻找导致未观察到 "A Task' 异常的原因...”

C# Collection<T>.Remove(T item) 尽管对象数据相等但不起作用

c# - 如何访问 x :Name-property in code?

c# - 如何在 TextBox Windows Phone 8.1 中更改文本的垂直对齐方式

C#:WPF MVVM 命令绑定(bind)与事件回调

c# - 为什么不允许在 .NET 中就地实现接口(interface)?

c# - 在 C# 中删除 datagridview 中的选定行?

c# - ICommand 的 CanExecuteChanged 事件