2012-08-16 96 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); 
     } 
    } 
}