2012-08-16 88 views
1

我有一个WPF自定义treeview类。 我想在字符串列表中获取选定的节点文本。获取在treeview中选择的节点

规则:

  • 如果父所有节点被选中,然后独自返回父节点的文本。
  • 如果没有选择父节点中的所有节点,则返回所选节点的parentName_childName列表。

    以上两条规则适用于所有级别。对于具有2级层次结构的树视图,返回名称为parentName_child1Name_child1ChildName

节点的模板C#代码:

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
namespace TreeViewCheckBox 
{ 
    public struct CheckBoxId 
    { 
     public static string IDCheckBox; 
    } 

    public class Node : INotifyPropertyChanged 
    { 
     private readonly ObservableCollection<Node> children = new ObservableCollection<Node>();  
     private readonly ObservableCollection<Node> parent = new ObservableCollection<Node>(); 
     private bool? isChecked = true; 
     private bool isExpanded; 
     private string text; 

     public Node() 
     { 
      this.Id = Guid.NewGuid().ToString(); 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     public ObservableCollection<Node> Children 
     { 
      get { return this.children; } 
     } 
     public string Id { get; set; } 
     public bool? IsChecked 
     { 
      get { return this.isChecked; } 
      set 
      { 
       this.isChecked = value; 
       this.RaisePropertyChanged("IsChecked"); 
      } 
     } 
     public bool IsExpanded 
     { 
      get { return this.isExpanded; } 
      set 
      { 
       this.isExpanded = value; 
       this.RaisePropertyChanged("IsExpanded"); 
      } 
     }  
     public ObservableCollection<Node> Parent 
     { 
      get { return this.parent; } 
     } 
     public string Text 
     { 
      get { return this.text; } 
      set 
      { 
       this.text = value; 
       this.RaisePropertyChanged("Text"); 
      } 
     } 
     private void CheckedTreeChild(IEnumerable<Node> items, int countCheck) 
     { 
      bool isNull = false; 
      foreach (Node paren in items) 
      { 
       foreach (Node child in paren.Children) 
       { 
        if (child.IsChecked == true || child.IsChecked == null) 
        { 
         countCheck++; 
         if (child.IsChecked == null) 
         { 
          isNull = true; 
         } 
        } 
       } 
       if (countCheck != paren.Children.Count && countCheck != 0) 
       { 
        paren.IsChecked = null; 
       } 
       else if (countCheck == 0) 
       { 
        paren.IsChecked = false; 
       } 
       else if (countCheck == paren.Children.Count && isNull) 
       { 
        paren.IsChecked = null; 
       } 
       else if (countCheck == paren.Children.Count && !isNull) 
       { 
        paren.IsChecked = true; 
       } 

       if (paren.Parent.Count != 0) 
       { 
        this.CheckedTreeChild(paren.Parent, 0); 
       } 
      } 
     } 
     private void CheckedTreeChildMiddle(
      IEnumerable<Node> itemsParent, IEnumerable<Node> itemsChild, bool? isCheckBoxChecked) 
     { 
      const int CountCheck = 0; 
      this.CheckedTreeParent(itemsChild, isCheckBoxChecked); 
      this.CheckedTreeChild(itemsParent, CountCheck); 
     } 
     private void CheckedTreeParent(IEnumerable<Node> items, bool? isCheckBoxChecked) 
     { 
      foreach (Node item in items) 
      { 
       item.IsChecked = isCheckBoxChecked; 
       if (item.Children.Count != 0) 
       { 
        this.CheckedTreeParent(item.Children, isCheckBoxChecked); 
       } 
      } 
     } 
     private void RaisePropertyChanged(string propertyName) 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 

      const int CountCheck = 0; 
      if (propertyName == "IsChecked") 
      { 
       if (this.Id == CheckBoxId.IDCheckBox && this.Parent.Count == 0 && this.Children.Count != 0) 
       { 
        this.CheckedTreeParent(this.Children, this.IsChecked); 
       } 

       if (this.Id == CheckBoxId.IDCheckBox && this.Parent.Count > 0 && this.Children.Count > 0) 
       { 
        this.CheckedTreeChildMiddle(this.Parent, this.Children, this.IsChecked); 
       } 

       if (this.Id == CheckBoxId.IDCheckBox && this.Parent.Count > 0 && this.Children.Count == 0) 
       { 
        this.CheckedTreeChild(this.Parent, CountCheck); 
       } 
      } 
     } 
    } 
} 

用户控件XAML代码:

<UserControl x:Class="TreeViewCheckBox.CustomTreeView" 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
       xmlns:TreeViewWithImageCheckBox="clr-namespace:TreeViewCheckBox" 
       mc:Ignorable="d"> 
     <UserControl.Resources> 
      <HierarchicalDataTemplate DataType="{x:Type TreeViewCheckBox:Node}" ItemsSource="{Binding Children}"> 
       <StackPanel Orientation="Horizontal"> 
        <StackPanel.Margin>2</StackPanel.Margin> 
        <CheckBox Margin="1" IsChecked="{Binding IsChecked}" 
           PreviewMouseLeftButtonDown="CheckBox_PreviewMouseLeftButtonDown" 
           Uid="{Binding Id}" /> 
        <TextBlock Margin="1" Text="{Binding Text}" /> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
      <Style TargetType="TreeViewItem"> 
       <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" /> 
      </Style> 
     </UserControl.Resources> 
     <Grid> 
      <TreeView Name="tvMain" Grid.ColumnSpan="2" x:FieldModifier="private" /> 
     </Grid> 
</UserControl> 

用户控件的C#代码:

using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Data; 
using System.Linq; 
using System.Windows.Controls; 
namespace TreeViewCheckBox 
{ 
    public partial class CustomTreeView 
    { 
     public CustomTreeView() 
     { 
      this.Nodes = new ObservableCollection<Node>(); 
      this.InitializeComponent(); 
      this.FillTree(); 
     } 
     private ObservableCollection<Node> Nodes { get; set; } 

     public void FillTree() 
     { 
      this.Nodes.Clear(); 
      for (int i = 0; i < 5; i++) 
      { 
       var level1Items = new Node { Text = " Level 1 Item " + (i + 1) }; 
       for (int j = 0; j < 2; j++) 
       { 
        var level2Items = new Node { Text = " Level 2 Item " + (j + 1) }; 
        level2Items.Parent.Add(level1Items); 
        level1Items.Children.Add(level2Items); 
        for (int n = 0; n < 2; n++) 
        { 
         var level3Items = new Node { Text = " Level 3 Item " + (n + 1) }; 
         level3Items.Parent.Add(level2Items); 
         level2Items.Children.Add(level3Items); 
        } 
       } 

       this.Nodes.Add(level1Items); 
      } 

      this.tvMain.ItemsSource = this.Nodes; 
     } 

     private void CheckBox_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) 
     { 
      var currentCheckBox = (CheckBox)sender; 
      CheckBoxId.IDCheckBox = currentCheckBox.Uid; 
     } 
    } 
    } 

如何获取列表中选定的节点?

回答

1

也许,您将不得不遍历Nodes集合并检查IsChecked属性的值。事情是这样的:

private List<string> SelectedNodes = new List<string>(); 

private void GetSelectedNodeText(NodeCollection nodes) 
{ 
    foreach (Node node in nodes) 
    { 
     if (node.IsChecked != true && node.IsChecked != false) 
     { 
      SelectedNodes.Add(node.Text + "_" + GetSelectedChildNodeText(node.ChildNodes)); 
     } 
     else if (node.IsChecked == true) 
     { 
      SelectedNodes.Add(node.Text); 
     } 
    } 
} 

private string GetSelectedChildNodeText(NodeCollection nodes) 
{ 
    string retValue = string.Empty; 

    foreach (Node node in nodes) 
    { 
     if (node.IsChecked != true && node.IsChecked != false) 
     { 
      retValue = node.Text + "_" + GetSelectedChildNodeText(node.ChildNodes); 
     } 
     else if (node.IsChecked == true) 
     { 
      retValue = node.Text; 
     } 
    } 

    return retVal; 
} 

我的假设:

  1. 的财产器isChecked具有真正的价值,当它所有的孩子都 选择。
  2. IsChecked属性在所有 儿童被取消选择时都具有错误值。
  3. 仅当选中某些子项时,IsChecked属性既没有为真 也没有错误值。
  4. 在Node.Text属性中有节点的文本。
+0

谢谢!但是你的代码只能选择层次结构中的一个节点:( – 2012-08-16 09:43:10

+0

嗯,我只是想写一个粗略的代码,很高兴它有帮助,如果你将它标记为一个有用的答案,会更加高兴! – Sandeep 2012-08-16 09:49:23

0

感谢Sandeep对他的想法。

下面的代码工作正常..

public List<string> GetSelectedNodes() 
{ 
    var listNodes = new List<string>(); 
    foreach (Node node in this.Nodes) 
    { 
     if (node.IsChecked == null) 
     { 
      this.GetSelectedChildNodeText(node.Text, node.Children, ref listNodes); 
     } 
     else if (node.IsChecked == true) 
     { 
      listNodes.Add(node.Text); 
     } 
    } 

    return listNodes; 
} 

private void GetSelectedChildNodeText(string nodeName, IEnumerable<Node> nodes, ref List<string> listNodes) 
{ 
    foreach (Node node in nodes) 
    { 
     string currentName = string.Format("{0}_{1}", nodeName, node.Text); 
     if (node.IsChecked == null) 
     { 
      this.GetSelectedChildNodeText(currentName, node.Children, ref listNodes); 
     } 
     else if (node.IsChecked == true) 
     { 
      listNodes.Add(currentName); 
     } 
    } 
} 
相关问题