Silverlight Treeview 相关操作:加载,保存,索引节点,节点移动,模板节点(收藏)

     最近一个Silverlight项目中,需要多处表达展示内容的“父子”关系。自然用“树”来表达自然是再好不过。Ms Toolkit中包含了TreeView控件,很好的满足了需求。
     要表述树状关系,数据库的设计一定要合理,不然这层关系在加载的时候就会很痛苦。另外,根据需求,树状节点的展示还要有一定的顺序,所以一棵树在保存的时候,每个节点在树中的位置也要有所记录。
     数据库设计

ContractedBlock.gif ExpandedBlockStart.gif
CREATE TABLE BASIC_INFO
(
  ID        
NUMBER(22,3),
  NAME      
VARCHAR2(100 BYTE),
  PARENTID  
NUMBER(22,3),
  GRADE     
NUMBER(1),
  MEMO      
VARCHAR2(100 BYTE),
  IDX       
NUMBER(5)
)

     这样,加载的时候就可以根据ID,ParentID找到父子关系,并根据IDX来加载ID在树中的索引。这个索引要从树的第一个节点开始深度遍历,根据遍历到的节点的顺序记录其索引。

-树的加载

 string sqlTv = "SELECT * FROM PDM_BASIC_INFO ORDER BY IDX ASC";

ContractedBlock.gif ExpandedBlockStart.gif
void client_getProjectInfoCompleted(object sender, getProjectInfoCompletedEventArgs e)
        {
                      
if (e.Error == null)
            {
                tvshow.Items.Clear();

ObservableCollection
<ProjectInfo> listsForProject = new ObservableCollection<ProjectInfo>();

                listsForProject 
= e.Result;

                
//添加Title Node
                TreeViewItem titleNode = new TreeViewItem();
                titleNode.FontSize 
= 15;

               
//为树加载标题节点
                
//titleNode.Background = new SolidColorBrush(Colors.Cyan);
                Grid gridTitle = getTitleGridTemplate();
                setTitleData(gridTitle);
                titleNode.Header 
= gridTitle;

                
// titleNode.Background = null;
                tvshow.Items.Add(titleNode);


                
///加载添加Node
                AddTreeNodeForProject(0null);

            
            }
            
else
            {
                MessageBox.Show(
"操作异常,请重新作业" + e.Error.Message, "注意", MessageBoxButton.OK);
            }
        }

 

ContractedBlock.gif ExpandedBlockStart.gif
     private void AddTreeNodeForProject(int parentID, TreeViewItem treeViewItem)
        {

            List
<ProjectInfo> result = (from Info in listsForProject
                                        
where Info.ParentID == parentID
                                        select Info).ToList
<ProjectInfo>();

            
if (result.Count > 0)
            {
                
foreach (ProjectInfo info in result)
                {
                    TreeViewItem objTreeNode 
= new TreeViewItem();
                    objTreeNode.IsExpanded 
= true;
                   
                    
//如果是叶子节点,为其加载模板控制项
                    if (info.Grade == 3//叶子节点绑定 时间控制项
                       {
                        Grid grid 
= getGridTemplate();
                        setGridData(grid, info.Name, info.ID);
                        objTreeNode.Header 
= grid;

                    }
                    
else
                    {
                        objTreeNode.Header 
= "[" + info.ID + "]" + info.Name;
                    }

                    
//添加根节点
                    if (treeViewItem == null)
                    {
                        tvshow.Items.Add(objTreeNode);
                    }
                    
else
                    {
                        treeViewItem.Items.Add(objTreeNode);
                    }
                    
//递归加载
                    AddTreeNodeForProject(info.ID, objTreeNode);
                }
            }
        }

 

 其中,节点的header属性为object类型,这样我们可以根据需求,为其赋予需要的控制项。

设置定制节点

ContractedBlock.gif ExpandedBlockStart.gif Code  void  setTitleData(Grid grid)
        {
            TextBlock Phase 
=  new  TextBlock();
            Phase.Text 
=  " Phase " ;


            Grid.SetColumn(Phase, 
0 );
            grid.Children.Add(Phase);

            Phase 
=  new  TextBlock();
            Phase.Text 
=  " Task " ;

            Grid.SetColumn(Phase, 
1 );
            grid.Children.Add(Phase);

            Phase 
=  new  TextBlock();
            Phase.Text 
=  " Item " ;

            Grid.SetColumn(Phase, 
2 );
            grid.Children.Add(Phase);

            Phase 
=  new  TextBlock();
            Phase.Text 
=  " 工期 " ;

            Grid.SetColumn(Phase, 
3 );
            grid.Children.Add(Phase);


            Phase 
=  new  TextBlock();
            Phase.Text 
=  " 开始时间 " ;

            Grid.SetColumn(Phase, 
4 );
            grid.Children.Add(Phase);

            Phase 
=  new  TextBlock();
            Phase.Text 
=  " 实际开始时间 " ;

            Grid.SetColumn(Phase, 
5 );
            grid.Children.Add(Phase);

            Phase 
=  new  TextBlock();
            Phase.Text 
=  " 完成时间 " ;

            Grid.SetColumn(Phase, 
6 );
            grid.Children.Add(Phase);

            Phase 
=  new  TextBlock();
            Phase.Text 
=  " 实际完成时间 " ;

            Grid.SetColumn(Phase, 
7 );
            grid.Children.Add(Phase);
        }

        
private  void  setGridData(Grid grid,  string  str,  int  id)
        {
            
// 序号
            TextBlock flag  =  new  TextBlock();
            flag.Tag 
=  id;
            Grid.SetColumn(flag, 
0 );
            grid.Children.Add(flag);

            
// 名称
            TextBlock lbl  =  new  TextBlock();
            lbl.Text 
=  " [ "  +  id.ToString()  +  " ] "  +  str;
            
// lbl.Text = str;
            Grid.SetColumn(lbl,  1 );
            grid.Children.Add(lbl);

            
// 工期
            TextBox txt  =  new  TextBox();
            txt.IsEnabled 
=  false ;
            Grid.SetColumn(txt, 
2 );
            grid.Children.Add(txt);

            
// 开始时间
            DatePicker dp  =  new  DatePicker();
            dp.IsEnabled 
=  false ;
            Grid.SetColumn(dp, 
3 );
            grid.Children.Add(dp);

            
// 实际开始时间
            dp  =  new  DatePicker();
            Grid.SetColumn(dp, 
4 );
            grid.Children.Add(dp);


            
// 完成时间
            dp  =  new  DatePicker();
            dp.IsEnabled 
=  false ;
            Grid.SetColumn(dp, 
5 );
            grid.Children.Add(dp);

            
// 实际完成时间
            dp  =  new  DatePicker();
            Grid.SetColumn(dp, 
6 );
            grid.Children.Add(dp);

        }

        
private  Grid getGridTemplate()
        {
            Grid grid 
=  new  Grid();
            RowDefinition row1 
=  new  RowDefinition();
            grid.RowDefinitions.Add(row1);

            
// id
            ColumnDefinition col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 1 );
            grid.ColumnDefinitions.Add(col);

            
// ITem Name
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 250 );
            grid.ColumnDefinitions.Add(col);

            
// 工期
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 50 );
            grid.ColumnDefinitions.Add(col);

            
// 计划开始时间
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 150 );
            grid.ColumnDefinitions.Add(col);

            
// 实际开始时间
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 150 );
            grid.ColumnDefinitions.Add(col);

            
// 完成时间
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 150 );
            grid.ColumnDefinitions.Add(col);

            
// 实际完成时间
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 150 );
            grid.ColumnDefinitions.Add(col);

            
return  grid;
        }

        
private  Grid getTitleGridTemplate()
        {
            Grid grid 
=  new  Grid();
            RowDefinition row1 
=  new  RowDefinition();

            grid.RowDefinitions.Add(row1);

            
// Phase
            ColumnDefinition col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 40 );
            grid.ColumnDefinitions.Add(col);

            
// task
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 50 );
            grid.ColumnDefinitions.Add(col);

            
// item
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 210 );
            grid.ColumnDefinitions.Add(col);

            
// 工期
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 50 );
            grid.ColumnDefinitions.Add(col);

            
// 计划开始时间
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 150 );
            grid.ColumnDefinitions.Add(col);

            
// 实际开始时间
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 150 );
            grid.ColumnDefinitions.Add(col);

            
// 计划完成时间
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 150 );
            grid.ColumnDefinitions.Add(col);

            
// 实际完成时间
            col  =  new  ColumnDefinition();
            col.Width 
=  new  GridLength( 150 );
            grid.ColumnDefinitions.Add(col);

            
return  grid;
        }

 Demo:

读取节点信息

ContractedBlock.gif ExpandedBlockStart.gif
for (int n = 0; n < items.Items.Count; n++//遍历ITems
                    {
                        TreeViewItem item 
= items.Items[n] as TreeViewItem;

                        Grid grid 
= item.Header as Grid;

                        TextBlock txtID 
= grid.Children[0as TextBlock;
                        DatePicker txtStart 
= grid.Children[4as DatePicker;
                        DatePicker txtEnd 
= grid.Children[6as DatePicker;
                    
                        
//code here

                    }

 

--=============
     另外,用户提出一些特定的需求:树状节点的顺序他们要自己调整。Liquid.Treeview控件,可以很好的实现节点的拖拽和移动,我们只需要在用户移动后深度遍历每个节点,并保存其位置索引信息即可。
    Liquid.Treeview节点的移动:

ContractedBlock.gif ExpandedBlockStart.gif
     Node node = tvshow.Selected;
            
if (node != null)
            {
                node.SwapPrevious();

                
// node.SwapNext();
            }


遍历保存节点索引

ContractedBlock.gif ExpandedBlockStart.gif
 ObservableCollection<PDMInfo> PDMInfos = new ObservableCollection<PDMInfo>();

            
int m = 0;

            PDMInfo info 
= new PDMInfo();

            
for (int i = 0; i < tvshow.Nodes.Count; i++//phase
            {
                Node phase 
= tvshow.Nodes[i] as Node;
                m 
= m + 1;

                
int PhaseID = Convert.ToInt32(phase.Tag);

                info 
= new PDMInfo()
                {
                    ID 
= PhaseID,
                    IDX 
= m
                };

                PDMInfos.Add(info);

                
for (int j = 0; j < phase.Nodes.Count; j++)
                {
                    Node task 
= phase.Nodes[j] as Node;

                    m 
= m + 1;
                    
int TaskID = Convert.ToInt32(task.Tag);

                    info 
= new PDMInfo()
                    {
                        ID 
= TaskID,
                        IDX 
= m
                    };

                    PDMInfos.Add(info);

                    
for (int n = 0; n < task.Nodes.Count; n++)
                    {
                        Node item 
= task.Nodes[n] as Node;

                        m 
= m + 1;
                        
int ItemID = Convert.ToInt32(item.Tag);

                        info 
= new PDMInfo()
                        {
                            ID 
= ItemID,
                            IDX 
= m
                        };

                        PDMInfos.Add(info);

                    }
                }
            }

            client.UpdatePDMInfoToDBCompleted 
+= new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_UpdatePDMInfoToDBCompleted);
            client.UpdatePDMInfoToDBAsync(PDMInfos);

转载于:https://www.cnblogs.com/yongbin621/archive/2009/03/20/1417448.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值