Silverlight为TreeView添加ChecKBox并实现父子选择操作

今天,要实现TreeView的多选,发现自己犯了好几个错误,其中有些错误已经犯了一次了,现在记下来,特别给自己一些警告。 实现效果如下

注意问题:

  1. TreeViewItem的Selected事件和UnSelected事件要注意。Selected事件:当TreeViewItem 的IsSelected属性 False更改为 True 时发生;UnSelected事件:当TreeViewItem的IsSelected属性 True 更改为 False时发生,也就是说当选择从此 TreeViewItem 更改为 TreeView 控件中的另一个 TreeViewItem 时,将发生该事件。(在这里我没有使用TreeViewItem的Selected/UnSelected事件,因为我没有实现我想要的功能,就改在 CheckBox上实现了)可查阅http://msdn.microsoft.com/zh-cn/library/system.windows.controls.treeviewitem.selected.aspx
  2. 在 TreeViewItem.Header中添加了CheckBox后,要注意CheckBox.Checked和CheckBox.Unchecked事 件的触发机制。因为在代码中不能再次使用递归方法了,如果用了,就会重复触发CheckBox的Checked和Unchecked事件;
  3. 在使用树节点的时候可以灵活的使用Tag属性。

实现代码如下:

  1. 进入页面后的OnLoaded()
  2. protected override void OnLoaded()
            {
                if (Resource.IsNullOrEmpty(SC.CurrentUser.Person))
                    UI.Alert(SR.NonOperationalStaff, SC.CurrentUser.Name);
                else
                {
                    currentUser = SC.CurrentUser;
                    //根据当前登录的用户,取得相应的职位/角色,因为进入页面时不相应的选择
                    searchDialog = new Dialog
                    {
                        Title = "选择要操作的客服人员",
                        Width = 400,
                        Height = 350,
                        Content = new Grid
                        {
                            RowDefinitions = { 
                                new RowDefinition {Height = new GridLength(1, GridUnitType.Star)},
                                new RowDefinition { Height = new GridLength(0,GridUnitType.Auto)} 
                           },
                            Margin = new Thickness(5),
                            Children =
                            {
                                (searchTreeView = new TreeView {BorderThickness = new Thickness(0)}).GridRow(0),
                                new WrapPanel{
                                    HorizontalAlignment = HorizontalAlignment.Center,
                                    Margin = new Thickness (5),
                                    Children = {
                                        new App.Windows.Controls.Button(){Content = "确认", Width = 60, Height=23}.Do( o => o.Click += new RoutedEventHandler(SearchDialogConfirm_Click)),
                                        new App.Windows.Controls.Button(){Content = "取消" , Width = 60,Height=23}.Do(o => o.Click +=new RoutedEventHandler(SearchDialogCancel_Click))
                                    }
                                }.GridRow(1)
                            
                            }
                        }
                    };
                    BuildTreeViewFilter();
                    searchDialog.Show();
                }
            }
  3. 生成树的结构
  4. void BuildTreeViewFilter()
            {
                Account currentAccount = SC.SelectOne(new Query<Account>(q => q.CurAccendant == currentUser && q.Customer == null).Span(s => new object[] { s.CurAccendant, s.CurAccendant.Person }));
    
                Employee employee = SC.SelectOne(new Query<Employee>(q => q.Person == currentUser.Person).Span(s => new object[] { s.Organization, s.Position, s.Person }));
                string tvHeaderName = "";
                if (employee != null)
                {
                    tvHeaderName = " (" + employee.Organization.Name + ":" + employee.Position.Name + ") ";// +(SC.Select(new Query<Account>(q => q.Parent.Key == currentAccount.Key)).Count).ToString();
                }            
    
                if (currentAccount != null)
                {
                    searchTreeView.Items.Clear();
                    TreeViewItem tviAccount = new TreeViewItem();
                    //tviAccount.FontSize = 15px;
                    //tviAccount.Background = new SolidColorBrush(Colors.Cyan);
    
                    tviAccount.Header = new WrapPanel
                    {
                        Children = { 
                                new CheckBox(){Content = currentAccount.CurAccendant.Name + tvHeaderName, Tag = currentAccount}
                                    .Do(o => 
                                    {
                                        o.Checked += TreeViewFilterAccount_Selected;
                                        o.Unchecked += TreeViewFilterAccount_Selected;
                                    })
                            }
                    };
                    tviAccount.Tag = currentAccount;
                    tviAccount.IsExpanded = true;
                    CreateChildTreeViewFilter(currentAccount, tviAccount);
                    searchTreeView.Items.Add(tviAccount);
                }
                       }
    
    void CreateChildTreeViewFilter(Account parentAccount, TreeViewItem currentTreeViewItem)
            {
                //必须是紫博蓝员工
                ResSet<Account> tvNode = SC.Select(new Query<Account>(q => q.Parent.Key == parentAccount.Key && q.Customer == null).Distinct().Span(s => new object[] { s.CurAccendant.Person, s.CurAccendant }));
    
                if (tvNode != null && tvNode.Count > 0)
                {
                    foreach (Account account in tvNode)
                    {
                        Employee employee = SC.SelectOne(new Query<Employee>(q => q.Person == account.CurAccendant.Person).Span(s => new object[] { s.Organization, s.Position, s.Person }));
                        string tvHeaderName = "";
                        if (employee != null)
                        {
                            tvHeaderName = " (" + employee.Organization.Name + ":" + employee.Position.Name + ")";// +(SC.Select(new Query<Account>(q => q.Parent.Key == account.Key)).Count).ToString();
                        }
    
                        TreeViewItem tviAccount = new TreeViewItem();
                        tviAccount.Header = new WrapPanel
                        {
                            Children = { 
                                    new CheckBox() { Content = account.CurAccendant.Name + tvHeaderName, Tag = account}
                                        .Do(o => 
                                        {
                                            o.Checked += TreeViewFilterAccount_Selected;
                                            o.Unchecked += TreeViewFilterAccount_Selected;
                                        })
                                }
                        };
                        tviAccount.Tag = account;
                        tviAccount.IsExpanded = true;
                        CreateChildTreeViewFilter(account, tviAccount);
                        currentTreeViewItem.Items.Add(tviAccount);
                    }
                }
            }

  5. 选 择树的节点:需要注意这里不能使用递归了,因为执行到chk.IsChecked = ((tvi.Header as WrapPanel).Children[0] as CheckBox).IsChecked;之后,还会触发相应的checked/Unchecked事件,所以就不需要递归了。

void TreeViewFilterAccount_Selected(object sender, RoutedEventArgs e)
        {
            //Account tvAccountFilter = (Account)((TreeViewItem)sender).Tag;
            
            //SetTreeViewFilterAccountSelectedStatus(tvAccountFilter);
            var tvi = GetTreeViewItem((sender as CheckBox).Tag as Account);
            SetTreeViewFilterAccountSelectedStatus(tvi);
        }

        TreeViewItem GetTreeViewItem(Account account)
        {
            foreach (TreeViewItem item in searchTreeView.Items)
            {
                if ((item.Tag as Account) == account)
                {
                    return item;
                }
                var tvi = GetTreeViewItem(item, account);
                if (tvi != null) return tvi;
            }
            return null;
        }

        TreeViewItem GetTreeViewItem(TreeViewItem parent, Account account)
        {
            foreach (TreeViewItem item in parent.Items)
            {
                if ((item.Tag as Account) == account)
                {
                    return item;
                }
                var tvi = GetTreeViewItem(item, account);
                if (tvi != null) return tvi;
            }
            return null;
        }

        void SetTreeViewFilterAccountSelectedStatus(TreeViewItem tvi)
        {
            foreach (TreeViewItem item in tvi.Items)
            {
                var chk = ((WrapPanel)item.Header).Children[0] as CheckBox;
                chk.IsChecked = ((tvi.Header as WrapPanel).Children[0] as CheckBox).IsChecked;
                //chk.IsChecked = !chk.IsChecked;            
                //SetTreeViewFilterAccountSelectedStatus(item);
            }
        }

 

 

这棵树还需要实现其它几个方面:checkbox我三种选择状态;checkbox的状态改变时还需要对其子树进行相应的处理。

共有0个回答