【wpf】 当用了数据模板之后如何获取控件的Item?

背景

 我对一个treeview使用了数据模板

                  
	
	
		
			
			
			
	

数据源的数据结构为:

public class ToolsNodeItem
    {

        public string Icon { get; set; }
        public string DisplayName { get; set; }


        //Tree的绑定源就要这样套娃!
        public ObservableCollection Children { get; set; }

        public ToolsNodeItem()
        {
            Children = new ObservableCollection();
        }

    }

完成后大概就是这个样子

【wpf】 当用了数据模板之后如何获取控件的Item?_第1张图片

 现在我的需求是,右键点击这些节点,弹出一个右键菜单然后对节点进行操作。比如删除这个节点。

弹出菜单不难:(加上这段就行)


    
        
        
        
    

现在问题来了,因为是右键菜单,你会发现右键单击后,菜单是弹出来了,但是此时节点并没有被选中,所以此时即使你为treeview设置了PreviewMouseLeftButtonDown这些事件,然后查看sender(treeview)发现,treeview的SelectItem依然是null,这样就无法确认到底是那个item别选中,就没办法对item操作。所以首先要想办法让右键能选中控件。

于是我需要将模板中的StackPanel添加鼠标右键事件:下面这种是MVVM的写法!

                 
	
	
		
			
				
					
				
			
			
				
					
					
					
				
			
			
			
			
				
			
				
	

这里需要说明一下:以前,我都是这么写的:


    

这样写,命令接收的参数就是我们平时使用事件的e的内容,但是由于我们用到了数据模板,导致e中的内容是和你点击的地方不同而不同的:【wpf】 当用了数据模板之后如何获取控件的Item?_第2张图片

 如果你点击的位置是TreeViewItem的图片位置,那么这里的OriginalSource以及Source就是Image,如果你点到的是文字位置对应的就是TextBlock。如果不使用数据模板的话,我们得到的其实就是TreeViewItem,然后使用TreeViewItem对象,调用Forks就好了。

用了数据版本就没法拿到TreeViewItem吗?

于是我咨询了一下老师:

【wpf】 当用了数据模板之后如何获取控件的Item?_第3张图片

 目前我认为,用了数据版本就基本没办法拿到TreeViewItem了。

于是就有了:

有了它,也拿不到TreeViewItem,但是得到了ToolsNodeItem,就是TreeViewItem对应的数据源的子项:(不管你点击TreeViewItem的哪个位置都一样)

【wpf】 当用了数据模板之后如何获取控件的Item?_第4张图片

ItemContainerStyle

回想到老师的这句话:

 我拿不到TreeViewItem但是我可以,绑定TreeViewItem的IsSelected属性啊!但是数据模板不是TreeViewItem啊?

这就要看 ItemContainerStyle 这个样式了,它规定了子项的样式,而该样式就可以设置属性IsSelected!

这个几个容易混淆的概念,大家可以对比一下:

这些都是,wpf给我提供的接口,“入侵” 控件内部的“密码”,只有搞清楚这些,我们才能更好的实现数据驱动界面!将bingding用的更加的灵活。

【wpf】 当用了数据模板之后如何获取控件的Item?_第5张图片

于是,我又在ToolsNodeItem模型中增加了一个属性IsSelected

【wpf】 当用了数据模板之后如何获取控件的Item?_第6张图片

private bool isSelected =false;

public bool IsSelected
{
    get { return isSelected; }
    set { SetProperty(ref isSelected, value); }
}

前台代码添加部分:

【wpf】 当用了数据模板之后如何获取控件的Item?_第7张图片

 BasedOn="{StaticResource {x:Type TreeViewItem}}"

这里的BasedOn是为了继续使用handcontrol的样式,覆盖默认的样式。

数据驱动界面

最后将ToolsNodeItem中的IsSelected设置为True,这样就能通过数据IsSelected,驱动界面TreeViewItem的IsSelected为True,从而选中。

【wpf】 当用了数据模板之后如何获取控件的Item?_第8张图片

所以使用了数据模板之后,就要将 数据驱动界面 进行到底。

结果展示

【wpf】 当用了数据模板之后如何获取控件的Item?_第9张图片

 实现了数据绑定之后,上下移动也是很简单的,移动数据源中的数据即可:

 private void WorkflowModify(string para)
 {
     var toolsNodeItem = workflowTreeViewObj.SelectedItem as ToolsNodeItem;
     if (toolsNodeItem != null)
     {
         var cur_index = WorkflowViewToolsTree.IndexOf(toolsNodeItem);
         if (para == "删除")
         {
             WorkflowViewToolsTree.Remove(toolsNodeItem);
         }
         else if (para == "上移")
         {
             cur_index = WorkflowViewToolsTree.IndexOf(toolsNodeItem);
             if (cur_index != 0)
             {
                 WorkflowViewToolsTree.Move(cur_index, cur_index-1);
             }
             else
             {
                 MessageBox.Show("到顶了");
             }
             
         }
         else if (para == "下移")
         {
             if (cur_index != WorkflowViewToolsTree.Count-1)
             {
                 WorkflowViewToolsTree.Move(cur_index, cur_index + 1);
             }
             else
             {
                 MessageBox.Show("到地板了");
             }
         }
     }
 }

番外

其实,用了模板后,有一种方法能拿到TreeViewItem

【wpf】 当用了数据模板之后如何获取控件的Item?_第10张图片

 不过也是,选中之后的事情了所以,不适合当前背景需求。

你可能感兴趣的:(WPF,wpf)