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


寫在前面:在(一)中,介紹了TreeView控件MVVM模式下數據綁定的方法。在這篇文章中,將總結給節點添加事件的方法,這樣說有些不對,總之實現的效果就是點擊某個節點,將出現對應於該節點的頁面或者數據。(我這里用的方法肯定不是最好的,但是是我能想到的最佳方法了,WPF初學者,希望大家多多指教。)


Example#1: 實現下圖功能,點擊左側treeview姓名節點,在右側會出現響應的detailed information. 可以將ID的textbox中的text屬性綁定到treeview中SelectedItem

先構造兩個類,一個是User,一個是TreeNode。User是TreeNode的一個屬性。

public class User
    {
        public string Key { get; set; }
        public string Name { get; set; }
        public int? Age { get; set; }
        
        public User()
        {
            Key = null;
            Name = null;
            Age = null;
        }
    }
User
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 User user { get; set; }


        public TreeNode()
        {
            ChildNodes = new List<TreeNode>();
            user = new User();
        }
    }
TreeNode

綁定:

<TreeView Grid.Column="0" FontSize="15" ItemsSource="{Binding Path=Nodes}" x:Name="treeview">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local:TreeNode}" ItemsSource="{Binding Path=ChildNodes}">
                    <Label Content="{Binding Path=NodeName}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

<TextBox Text="{Binding ElementName=treeview, Path=SelectedItem.user.Key}" Canvas.Left="70" Width="200" Canvas.Top="8"
                         FontSize="15"/>

<TextBox Text="{Binding ElementName=treeview, Path=SelectedItem.user.Age}" Canvas.Left="70" Width="200" Canvas.Top="8"
                         FontSize="15"/>

上面兩句TextBox控件,就是將項目中名為“treeview"的控件的SelectedItem.user.Key和SeletedItem.user.Age的值綁定到Text屬性中。這樣點”Lily"節點,右側就會出現相應的信息。

 

Example#2:

上面的例子比較簡單,第二個例子將button控件作為treeviewitem,並給button控件綁定一個Command。

場景描述:左側是treeview,其中每個treeviewitem的元素都是button控件,點擊每個節點,中間的listview中會出現符合條件的學生的姓名,比如,是Grade1的學生有Lucy, Tom和Lily三人。是Grade2Class1的學生有Sam和Jack兩人。點擊listview中的學生姓名,右側會顯示學生的ID和Age信息。

TreeView部分的XAML代碼:

<TreeView Grid.Column="0" FontSize="15" ItemsSource="{Binding Path=Nodes}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local:TreeNode}" ItemsSource="{Binding Path=ChildNodes}">
                    <Button Content="{Binding NodeName}" Command="{Binding DataContext.TreeViewCommand,
                        RelativeSource={RelativeSource AncestorType=local:MainWindow}}" CommandParameter="{Binding Path=NodeID}"
                            Background="White" BorderThickness="0"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

可以看見,TreeViewItem元素從Label變成了Button。其中Button控件綁定了一個TreeViewCommand。這里需要指明綁定的是DataContext下的TreeViewCommand,否則默認的是TreeNode類型中的TreeViewCommand屬性。因此下面這句是非常關鍵的。

Command="{Binding DataContext.TreeViewCommand,
                        RelativeSource={RelativeSource AncestorType=local:MainWindow}}" CommandParameter="{Binding Path=NodeID}"

ListView部分的XAML代碼:

<ListView Name="listview" Grid.Column="1" ItemsSource="{Binding Users}" IsSynchronizedWithCurrentItem="True"
                   BorderBrush="DarkGray" BorderThickness="5">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}" Width="auto"/>
                </GridView>
            </ListView.View>
        </ListView>

ViewModel代碼:

public class ViewModel :INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private List<User> userlist = new List<User>();
        private List<TreeNode> nodes;
        public List<TreeNode> Nodes
        {
            get { return nodes; }
            set { nodes = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("Nodes"));
            }
        }
        private List<User> users = new List<User>();
        public List<User> Users
        {
            get { return users; }
            set { users = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("Users"));
            }

        }

   

        public DelegateCommand TreeViewCommand { get; }

        public ViewModel()
        {
            // 初始化Nodes和Users,一般Users是要訪問數據庫得到的,這里進行了簡化。
            InitiateNodes();
            InitiateUsers();
            TreeViewCommand = new DelegateCommand(TreeViewCommandHandler);
        }

        private void TreeViewCommandHandler(object sender, DelegateCommandEventArgs e)
        {
            int id = Convert.ToInt32(e.Parameter);
            switch (id)
            {
                case 1:
                    Users = userlist.Where(x => x.GradeNum == 1).ToList();
                    break;
                case 2:
                    Users = userlist.Where(x => x.GradeNum == 2).ToList();
                    break;
                case 3:
                    Users = userlist.Where(x => x.GradeNum == 3).ToList();
                    break;
                case 4:
                    Users = userlist.Where(x => x.GradeNum == 1 && x.ClassNum == 1).ToList();
                    break;
                case 5:
                    Users = userlist.Where(x => x.GradeNum == 1 && x.ClassNum == 2).ToList();
                    break;
                case 6:
                    Users = userlist.Where(x => x.GradeNum == 2 && x.ClassNum == 1).ToList();
                    break;
                case 7:
                    Users = userlist.Where(x => x.GradeNum == 2 && x.ClassNum == 2).ToList();
                    break;
                case 8:
                    Users = userlist.Where(x => x.GradeNum == 3 && x.ClassNum == 1).ToList();
                    break;
                case 9:
                    Users = userlist.Where(x => x.GradeNum == 3 && x.ClassNum == 2).ToList();
                    break;
            }
        }

        #region Initial methods
        private void InitiateNodes()
        {
            List<TreeNode> _nodes = new List<TreeNode>()
            {
                new TreeNode()
                {
                    ParentID=0,NodeID=1,NodeName="Grade1"
                },
                new TreeNode()
                {
                    ParentID=0,NodeID=2,NodeName="Grade2"
                },
                new TreeNode()
                {
                    ParentID=0, NodeID=3, NodeName="Grade3"
                },
                new TreeNode(){ParentID=1,NodeID=4,NodeName="Class1"},
                new TreeNode(){ParentID=1,NodeID=5,NodeName="Class2"},
                new TreeNode(){ParentID=2,NodeID=6,NodeName="Class1"},
                new TreeNode(){ParentID=2, NodeID=7, NodeName="Class2"},
                new TreeNode(){ParentID=3, NodeID=8, NodeName="Class1"},
                new TreeNode(){ParentID=3, NodeID=9, NodeName="Class2"}
            };
            Nodes = 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;
        }

        private void InitiateUsers()
        {
            User Lily = new User()
            {
                Name = "Lily",
                Age = 12,
                GradeNum = 1,
                ClassNum = 1
            };
            User Tom = new User()
            {
                Name = "Tom",
                Age = 11,
                GradeNum = 1,
                ClassNum = 1
            };
            User Lucy = new User()
            {
                Name = "Lucy",
                Age = 12,
                GradeNum = 1,
                ClassNum = 2
            };
            User Sam = new User()
            {
                Name = "Sam",
                Age = 13,
                GradeNum = 2,
                ClassNum = 1
            };
            User Jack = new User() { Name = "Jack", Age = 13, GradeNum = 2, ClassNum = 1 };
            User Ray = new User() { Name = "Ray", Age = 13, GradeNum = 2, ClassNum = 2 };
            User Lisa = new User() { Name = "Lisa", Age = 14, GradeNum = 3, ClassNum = 1 };
            User Liz = new User() { Name = "Liz", Age = 14, GradeNum = 3, ClassNum = 2 };
            userlist.Add(Liz);
            userlist.Add(Lisa);
            userlist.Add(Sam);
            userlist.Add(Lucy);
            userlist.Add(Tom);
            userlist.Add(Lily);
            userlist.Add(Jack);
            userlist.Add(Ray);
        }

        #endregion
    }
ViewModel

其中有兩個類,DelegateCommand和DelegateCommandEventArgs,是繼承自ICommand,然后委托方法的。

public class DelegateCommand : ICommand
    {
        // 定義一個名為SimpleEventHandler的委托,兩個參數,一個object類,一個是自定義的DelegateCommandEventArgs類
        public delegate void SimpleEventHandler(object sender, DelegateCommandEventArgs e);
        // handler是方法,別忘了,委托是用於定義方法的類
        private SimpleEventHandler handler;
        private bool isEnabled = true;

        public DelegateCommand(SimpleEventHandler handler)
        {
            this.handler = handler;
        }
        public void Execute(object parameter)
        {
            this.handler(this, new DelegateCommandEventArgs(parameter));
        }
        public bool CanExecute(object parameter)
        {
            return this.isEnabled;
        }
        public event EventHandler CanExecuteChanged;
        public bool IsEnabled
        {
            get { return this.isEnabled; }
            set
            {
                this.isEnabled = value;
                this.OnCanExecuteChanged();
            }
        }
        private void OnCanExecuteChanged()
        {
            if (this.CanExecuteChanged != null)
                this.CanExecuteChanged(this, EventArgs.Empty);
        }
    }
DelegateCommand
public class DelegateCommandEventArgs : EventArgs
    {
        private object parameter;
        public DelegateCommandEventArgs(object parameter)
        {
            this.parameter = parameter;
        }
        public object Parameter
        {
            get { return this.parameter; }
        }
    }
DelegateCommandEventArgs

2020.06.25更新內容

之前使用Button控件作為TreeViewItem,然后為Button的Command屬性綁定事件。更新為直接將事件綁定為TreeView的SelectedItemChanged屬性,同樣可以實現一樣的效果。詳情可見:

https://www.cnblogs.com/larissa-0464/p/13186486.html


免責聲明!

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



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