如何使指定的节点被选中

问题描述:在我的程序中有一个CTreeView视图,现在知道该视图中某个树节点的TVITEM结构体中的pszText和lParam两个参数,我要通过代码把该节点选中以触发TVN_SELCHANGING消息的发送。

解决办法一:

CWellTreeView* treeview=(CWellTreeView*)GetView(RUNTIME_CLASS(CWellTreeView));

treeview->OnInitialUpdate();

treeview->treeCtrl.SetFocus();

treeview->treeCtrl.Expand(treeview->treeCtrl.GetRootItem(),TVE_EXPAND);

TVITEM tvi;

 tvi.mask=TVIF_HANDLE|TVIF_PARAM;

tvi.lParam=m_iWellNumber;//m_iWellNumber对应要被选中节点的lParam参数

treeview->treeCtrl.GetItem(&tvi);

treeview->treeCtrl.SelectItem(tvi.hItem);

经过实验,该方法无效,节点根本就没有被选中!调试运行发现tvi.hItem的值始终为0xcccccccc,所以节点句柄根本就没有传进来。

 

解决办法二:

CWellTreeView* treeview=(CWellTreeView*)GetView(RUNTIME_CLASS(CWellTreeView));

treeview->OnInitialUpdate();

treeview->treeCtrl.SetFocus();

treeview->treeCtrl.Expand(treeview->treeCtrl.GetRootItem(),TVE_EXPAND);

char buff[80];

wsprintf(buff,"%s",m_strWellName);//m_strWellName对应要被选中节点的pszText参数

TVITEM tvi;

tvi.mask=TVIF_HANDLE|TVIF_TEXT;

tvi.pszText=buff;

tvi.cchTextMax=80;

treeview->treeCtrl.GetItem(&tvi);

treeview->treeCtrl.SelectItem(tvi.hItem);

第二种方法得到了第一种方法同样的结果,连节点句柄都没有传进去。

 

以上我自己想的两种方法不能解决,我只好上论坛求救,可是两天来我两度发帖,始终没有得到满意的解答,无奈只好自己再次推敲代码,问题肯定出在节点句柄上,于是我想了另外一种方法,在一个节点被选中的同时,把该节点句柄存储在CTreeView的一个成员变量m_pCurrItem中,

解决办法三:

CWellTreeView* treeview=(CWellTreeView*)GetView(RUNTIME_CLASS(CWellTreeView));

treeview->OnInitialUpdate();

treeview->treeCtrl.SetFocus();

treeview->treeCtrl.Expand(treeview->treeCtrl.GetRootItem(),TVE_EXPAND);

treeview->treeCtrl.SelectItem(treeview->m_hCurrItem);

但是我再次遭到了打击,节点还是没有被选中,m_hCurrItem倒是有了值,但这是我意料之中的事情。

但是选中最后一个节点的操作却可以实现:

CWellTreeView* treeview=(CWellTreeView*)GetView(RUNTIME_CLASS(CWellTreeView));

treeview->OnInitialUpdate();

treeview->treeCtrl.SetFocus();

treeview->treeCtrl.Expand(treeview->treeCtrl.GetRootItem(),TVE_EXPAND);

HTREEITEM hitem=treeview->treeCtrl.GetNextItem(NULL,TVGN_LASTVISIBLE);

treeview->treeCtrl.SelectItem(hitem);

这样也可以实现:

CWellTreeView* treeview=(CWellTreeView*)GetView(RUNTIME_CLASS(CWellTreeView));

treeCtrl.SelectItem(treeCtrl.GetRootItem());

treeCtrl.SelectItem(hitem);

也就是出现了这样的症状:如果调用OnInitialUpdate了以后,可以选中最后一个结点但不可以选中其他节点;如果不OnInitialUpdate,就可以选中任意节点。矛盾出现了:如果改变了某个节点的属性(如pszText),必须OnInitialUpdate更新,但是此节点又不是最后一个,此节点也不能选中。为什么OnInitialUpdate以后就只能选中最后一个几点呢?我们还是应该在句柄上找问题,有一点我们不能质疑:GetNextItem(NULL,TVGN_LASTVISIBLE)一定可以准确的获取最后一个节点的句柄。我们却不能肯定m_hCurrItem中存储的一定是当前要选中的节点,貌似是OnInitialUpdate捣的鬼,没错!OnInitialUpdate以后,虽然树节点有可能没有变化,但是节点句柄却会发生变化,也就是说m_hCurrItem不一定代表当前节点。

经过上面分析,我们可以想出如下对策:不采用句柄变量来存储当前节点句柄,而是采用动态句柄数组来存贮,在OnInitialUpdate中把更新后的节点句柄存贮在句柄数组中,句柄数组中存贮的一定是最新的节点句柄。另外,为了是程序更“面向对象”,我把选中当前节点操作放在CWellTreeView类中实现:

void CWellTreeView::SelectCurrItem(long i) {  

OnInitialUpdate();

 treeCtrl.SetFocus();  

treeCtrl.Expand(treeCtrl.GetRootItem(),TVE_EXPAND);  

treeCtrl.SelectItem(m_hCurrItem[i]);

}

这便是终极解法,前面几种解法基本没有利用价值。不仅节点被选中,TVN_SELCHANGING消息也被发送成功!

 

 

我还要说明两点点东西: 1.TVN_SELCHANGING消息只是在节点选择改变时才被发送,两次选择同一个几点,第二次选择时不会发送TVN_SELCHANGING消息。 2.使用GetItem必须要给出Item的句柄。以下信息摘自MSDN中TVM_GETITEM消息的说明: When the message is sent, the hItem member of the TVITEM or TVITEMEX structure identifies the item to retrieve information about, and the mask member specifies the attributes to retrieve.

初学者在学习过程中必然会遇到很多问题,我指的不仅仅是程序员,无论做什么。所以我没有抱怨自己。我总是在一切水落石出时才发现,原来问题就出在我一个小小的疏忽上面。是的,只有逻辑思维严密的人才有资格成为优秀的程序员!

在C#中,要在WPF的TreeView控件中选中指定节点,可以按照以下步骤进行: 1. **初始化TreeView节点**[^1]: ```csharp // 创建一个TreeView实例 TreeView treeView = new TreeView(); // 定义一个自定义节点的数据模型(这里假设它有一个DisplayName属性) class NodeData { public string ID { get; set; } public string DisplayName { get; set; } } // 创建树形结构的数据源 var data = new List<NodeData> { ... }; // 根据实际需求填充数据 // 为每个节点添加到TreeView中 foreach (var nodeData in data) { TreeNode treeNode = new TreeNode(nodeData.DisplayName); treeView.Nodes.Add(treeNode); } ``` 2. **选中指定节点**: - **通过节点ID**: ```csharp // 如果知道节点的ID,可以直接找到并设置IsSelected属性 TreeNode selectedNode = treeView.Nodes.FirstOrDefault(n => n.Tag == "yourNodeId"); if (selectedNode != null) selectedNode.IsSelected = true; ``` - **通过DisplayName**: ```csharp // 如果要根据DisplayName选择,可能需要遍历整个树结构 selectedNode = treeView.Nodes.Find($"Display Name: {targetDisplayName}", false); if (selectedNode != null) selectedNode.IsSelected = true; ``` 3. **动态更新选中状态**[^2]: 当进行节点移动(如上移或下移)操作后,可以通过更新节点的层次关系来保持选中状态: ```csharp void MoveNode(TreeNode oldParent, TreeNode newNode) { oldParent.Nodes.Remove(newNode); // 移除旧位置 newNode.Parent = oldParent.Parent; // 设置新位置 oldParent.Parent.Nodes.Insert(oldParent.Index + 1, newNode); // 插入新位置 // 更新选中状态 if (newNode.IsSelected) treeView.SelectedItem = newNode; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值