WPF中TreeView控件數據綁定和后台動態添加數據(一)


數據綁定:

更新內容:補充在MVVM模式上的TreeView控件數據綁定的代碼。

xaml代碼:

<TreeView Name="syntaxTree" ItemsSource="{Binding TreeNodes}">
                                <TreeView.ItemTemplate>
                                    <HierarchicalDataTemplate DataType="{x:Type local:TreeNode}" ItemsSource="{Binding Path=ChildNodes}">
                                        <TextBlock Text="{Binding NodeName}"/>
                                    </HierarchicalDataTemplate>
                                </TreeView.ItemTemplate>
</TreeView>

TreeView中的ItemsSource綁定的是一個名為TreeNodes的TreeNode的列表,即List<TreeNode>TreeNodes。HierarchicalDataTemplate中的ItemsSource綁定的TreeNodes中的每個節點的ChildNodes屬性。

ViewModel.cs中的代碼(有刪減):

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private List<TreeNode> treenodes = new List<TreeNode>();
    public List<TreeNode> TreeNodes
    {
       get { return treenodes; }
       set
       {
          treenodes = value;
          if (PropertyChanged != null)
             PropertyChanged(this, new PropertyChangedEventArgs("TreeNodes"));
       }
    }

    public ViewModel()
    {
    // Nodes是我已經獲得的一組節點
       TreeNodes = getChildNodes(0,Nodes);
    }

    private List<TreeNode> getChildNodes(int parentID, List<TreeNode> nodes)
    {
       List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
       List<TreeNode> otherNodes = nodes.Where(x => x.ParentID != parentID).ToList();
       foreach (TreeNode node in mainNodes)
          node.ChildNodes = getChildNodes(node.NodeID, otherNodes);
       return mainNodes;
    }
}

使用MVVM模式,那么xaml.cs文件就會變得非常簡單了,基本只有一句代碼了:

this.DataContext = new ViewModel();

該模式的好處就是使得UI設計和后端代碼分開,只通過數據綁定進行連接。嘗試用了幾次,真的還蠻方便。


 

TreeView數據綁定需要使用層次結構數據模板(HierarchicalDataTemplate)來顯示分層數據。XAML代碼如下:

<TreeView Name="chapterTree" Grid.Column="0">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=ChildNodes}">
                    <StackPanel>
                        <Label Content="{Binding Path=NodeName}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

其中,ItemsSource綁定的對象ChildNodes應該是一個集合類型:List<TreeNode>,Label中綁定的是TreeNode的NodeName屬性,TreeNode類定義如下所示:

public class TreeNode
    {
        public int NodeID { get; set; }
        public int ParentID { get; set; }
        public string NodeName { get; set; }
        public List<TreeNode> ChildNodes { get; set; }
        public TreeNode()
        {
            ChildNodes = new List<TreeNode>();
        }
    }

因為是樹形結構,因此TreeNode需要有NodeID屬性和ParentID屬性,即某個樹節點node本身的ID和它所屬的父節點的ID。以目錄為例,則xaml.cs中的代碼如下。首先是寫入了數據,在我實際項目中,這些數據是從DB中查詢的,這里為了簡化,直接Input數據了。

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            InputData();
            chapterTree.ItemsSource = getNodes(0, nodes);
        }

        private List<TreeNode> nodes;
        private void InputData()
        {
            nodes = new List<TreeNode>()
            {
                new TreeNode(){ParentID=0, NodeID=1, NodeName = "Chapter1" },
                new TreeNode(){ParentID=0, NodeID=2, NodeName="Chapter2"},
                new TreeNode(){ParentID=0,NodeID=3, NodeName="Chapter3"},
                new TreeNode(){ParentID=1, NodeID=4, NodeName="Section1.1"},
                new TreeNode(){ParentID=1, NodeID=5, NodeName="Section1.2"},
                new TreeNode(){ParentID=2, NodeID=6, NodeName="Section2.1"},
                new TreeNode(){ParentID=3, NodeID=7, NodeName="Section3.1"},
                new TreeNode(){ParentID=6, NodeID=8, NodeName="SubSection2.1.1"},
                new TreeNode(){ParentID=6, NodeID=9, NodeName="SubSection2.1.2"},
                new TreeNode(){ParentID=2, NodeID=10,NodeName="Section2.2"},
                new TreeNode(){ParentID=3, NodeID=11, NodeName="Section3.2"}
            };
        }
        private List<TreeNode> getNodes(int parentID, List<TreeNode> nodes)
        {
            List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
            List<TreeNode> otherNodes = nodes.Where(x => x.ParentID != parentID).ToList();
            foreach (TreeNode node in mainNodes)
                node.ChildNodes = getNodes(node.NodeID, otherNodes);
            return mainNodes;
        }
    }

需要注意的就是NodeID是不斷增加的,每個節點都有自己的ID,而其ParentID就看它是屬於哪個父節點的了。getNodes()是一個遞歸方法,就是不斷讀取某個節點的子節點。運行結果如圖所示:

 

后台動態添加TreeView:

一開始,沒用數據綁定,就直接在xaml.cs中使用treeview,雖然后來用了數據綁定之后發現還是綁定更方便,但是這種在后台構建treeview的方法沒准哪天也能用到,就記錄一下吧。

XAML文件,使用一個TreeView控件

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="60*"/>
            <ColumnDefinition Width="100*"/>
        </Grid.ColumnDefinitions>
        <TreeView Name="chapterTree" Grid.Column="0"/>
    </Grid>

XAML.CS文件,同樣使用遞歸方法,就是不斷的新建treeviewitem控件。

public partial class DynamicTreeView : Window
    {
        public DynamicTreeView()
        {
            InitializeComponent();
            InputData();
            ShowTreeView();
        }

        private List<TreeNode> nodes;
        private void InputData()
        {
            nodes = new List<TreeNode>()
            {
                new TreeNode(){ParentID=0, NodeID=1, NodeName = "Chapter1" },
                new TreeNode(){ParentID=0, NodeID=2, NodeName="Chapter2"},
                new TreeNode(){ParentID=0,NodeID=3, NodeName="Chapter3"},
                new TreeNode(){ParentID=1, NodeID=4, NodeName="Section1.1"},
                new TreeNode(){ParentID=1, NodeID=5, NodeName="Section1.2"},
                new TreeNode(){ParentID=2, NodeID=6, NodeName="Section2.1"},
                new TreeNode(){ParentID=3, NodeID=7, NodeName="Section3.1"},
                new TreeNode(){ParentID=6, NodeID=8, NodeName="SubSection2.1.1"},
                new TreeNode(){ParentID=6, NodeID=9, NodeName="SubSection2.1.2"},
                new TreeNode(){ParentID=2, NodeID=10,NodeName="Section2.2"},
                new TreeNode(){ParentID=3, NodeID=11, NodeName="Section3.2"}
            };
        }

        private void ShowTreeView()
        {
            TreeViewItem tv1 = new TreeViewItem();
            chapterTree.Items.Add(tv1);
            GetNodes(0, tv1);
        }

        private void GetNodes(int parentID, TreeViewItem tv)
        {
            List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
            foreach(var item in mainNodes)
            {
                TreeViewItem tv1 = new TreeViewItem();
                tv1.Header = item.NodeName;
                tv.Items.Add(tv1);
                GetNodes(item.NodeID, tv1);
            }
        }
    }

運行圖:總歸是沒有databinding方便。剛開始學習WPF,一開始沒想過要用數據綁定,總感覺只要能實現自己想要的東西就可以了,不用管實現過程,后來使用了之后發現,使用數據綁定構建MVVM架構的應用還是挺好的。

 第二部分將總結給節點添加事件的方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM