【问题标题】:WPF TreeView MultiSelect BehaviorWPF TreeView 多选行为
【发布时间】:2013-01-28 00:46:20
【问题描述】:

我根据这篇帖子写了一个多选行为:WPF TreeView with Multiple Selection

但是我的行为似乎没有按预期工作..你能帮忙吗?

以下是我的 xaml 代码:

 <Window x:Class="TreeView.Spike.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Spike="clr-namespace:TreeView.Spike" 
             Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
        </Window.Resources>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width=".5*"/>
                <ColumnDefinition Width=".5*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="40"></RowDefinition>
            </Grid.RowDefinitions>

            <TreeView ItemsSource="{Binding Nodes}" Grid.Row="0" x:Name="treeView" Grid.Column="0">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Name}">                  
                        </TextBlock>
                        </StackPanel>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
                <TreeView.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Add"></MenuItem>
                        <MenuItem Header="Delete"></MenuItem>
                    </ContextMenu>
                </TreeView.ContextMenu>
               <i:Interaction.Behaviors>
    <Spike:MultipleItemSelectionAttachedBehavior AllSelectedItems="{Binding Path=AllSelectedNodes}"/>
</i:Interaction.Behaviors>
            </TreeView>

        </Grid>
    </Window>

我的附加行为:

   public class MultipleItemSelectionAttachedBehavior:Behavior<System.Windows.Controls.TreeView>
        {
            public static DependencyProperty AllSelectedItemsProperty =
            DependencyProperty.RegisterAttached("AllSelectedItems", typeof(object), typeof(MultipleItemSelectionAttachedBehavior),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Inherits));

            private static readonly PropertyInfo IsSelectionChangeActiveProperty = typeof(System.Windows.Controls.TreeView).GetProperty("IsSelectionChangeActive",
              BindingFlags.NonPublic | BindingFlags.Instance);

            public object AllSelectedItems
            {
                get
                {
                    return (object)GetValue(AllSelectedItemsProperty);
                }
                set
                {
                    SetValue(AllSelectedItemsProperty, value);
                }
            }

            public static bool GetAllSelectedItems(DependencyObject obj)
            {
                return (bool)obj.GetValue(AllSelectedItemsProperty);
            }

            public static void SetAllSelectedItems(DependencyObject obj, bool value)
            {
                obj.SetValue(AllSelectedItemsProperty, value);
            }

            protected override void OnAttached()
            {
                base.OnAttached();
                AssociatedObject.SelectedItemChanged += AssociatedObject_SelectedItemChanged;
            }

            protected override void OnDetaching()
            {
                base.OnDetaching();
                AssociatedObject.SelectedItemChanged -= AssociatedObject_SelectedItemChanged;
            }

            void AssociatedObject_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
            {
                if (IsSelectionChangeActiveProperty == null) return;

                var selectedItems = new List<Node>();

                var treeViewItem = AssociatedObject.SelectedItem as Node;
                if (treeViewItem == null) return;

                // allow multiple selection
                // when control key is pressed
                if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
                {
                    var isSelectionChangeActive = IsSelectionChangeActiveProperty.GetValue(AssociatedObject, null);

                    IsSelectionChangeActiveProperty.SetValue(AssociatedObject, true, null);
                    selectedItems.ForEach(item => item.IsSelected = true);

                    IsSelectionChangeActiveProperty.SetValue(AssociatedObject, isSelectionChangeActive, null);
                }
                else
                {
                    // deselect all selected items except the current one
                    selectedItems.ForEach(item => item.IsSelected = (item == treeViewItem));
                    selectedItems.Clear();
                }

                if (!selectedItems.Contains(treeViewItem))
                {
                    selectedItems.Add(treeViewItem);
                }
                else
                {
                    // deselect if already selected
                    treeViewItem.IsSelected = false;
                    selectedItems.Remove(treeViewItem);
                }

                AllSelectedItems = selectedItems;
            }
        }

..还有我的 ViewModel

 public class ViewModel :NotificationObject
        {
            public ViewModel()
            {
                AllSelectedNodes = new ObservableCollection<Node>();
            }
     private ObservableCollection<Node> _allSelectedNodes;
            public ObservableCollection<Node> AllSelectedNodes
            {
                get { return _allSelectedNodes; }
                set
                {
                    _allSelectedNodes = value;
                    RaisePropertyChanged(() => AllSelectedNodes);   
                }
            }
    }

我的模特:

 public class Node:NotificationObject
        {

            private string _name;
            public string Name
            {
                get { return _name; }
                set
                {
                    _name = value;
                    RaisePropertyChanged(() => Name);   
                }
            }




            private bool _isExpanded = true;
            public bool IsExpanded
            {
                get { return _isExpanded; }
                set
                {
                    _isExpanded = value;
                    RaisePropertyChanged(() => IsExpanded); 
                }
            }

            private bool _isSelected;

            public bool IsSelected
            {
                get { return _isSelected; }
                set
                {
                    _isSelected = value;
                    RaisePropertyChanged(() => IsSelected);

                }
            }

            private ObservableCollection<Node> _nodes;
            public ObservableCollection<Node> Nodes
            {
                get { return _nodes; }
                set
                {
                    _nodes = value;
                    RaisePropertyChanged(() => Nodes);  
                }
            }

            public static IList<Node> Create()
            {
                return new List<Node>()
                           {
                               new Node()
                                   {
                                       Name = "Activity",
                                       Nodes = new ObservableCollection<Node>()
                                                   {
                                                       new Node() {Name = "Company",Nodes = new ObservableCollection<Node>(){  new Node() {Name = "Company1",Existing = false}}},
                                                         new Node() {Name = "Strategy",Nodes = new ObservableCollection<Node>(){  new Node() {Name = "Strategy1"}}},
                                                            new Node() {Name = "Vehicle",Nodes = new ObservableCollection<Node>(){  new Node() {Name = "Vehicle1",Existing = false}}}
                                                   }
                                   }
                           };
            }
        }

..还有我的初始化代码:

  public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var viewModel = new ViewModel();
            this.DataContext = viewModel;
            viewModel.Nodes = new ObservableCollection<Node>(Node.Create());

        }
}

问题是,它仍然只选择一个,而它应该在按住控制键的同时选择多个。

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    您需要像这样将选择模式属性添加到树视图

    SelectionMode="Multiple"
    

    【讨论】:

      【解决方案2】:

      您缺少 IsSelected 属性的绑定:

          <TreeView.ItemContainerStyle>
                 <Style TargetType="TreeViewItem">
                    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
                 </Style>
           </TreeView.ItemContainerStyle>
      

      【讨论】:

        【解决方案3】:

        在 AssociatedObject_SelectedItemChanged 中,当您刚刚实例化它时,selectedItems 的计数是零,还是稍后将 treeViewItem 添加到它时计数为 1?尝试将其设置为 AllSelectedItems 属性。此外,AllSelectedItems 属性不应该是某种列表或 IEnumerable 吗?

          if(AllSelectedItems == null)
          {
              AllSelectedItems = new List<Node>();
          }
          List<Node> selectedItems = AllSelectedItems;
        

        【讨论】:

        • List&lt;Node&gt; selectedItems = SelectedItems; 应该是List&lt;Node&gt; selectedItems = AllSelectedItems;
        猜你喜欢
        • 1970-01-01
        • 2010-11-12
        • 2011-08-23
        • 2011-07-19
        • 2013-05-13
        • 2015-10-12
        • 1970-01-01
        • 2011-04-01
        • 1970-01-01
        相关资源
        最近更新 更多