OnNewText事件后何时重绘VirtualTreeView? [英] When to redraw VirtualTreeView after OnNewText event?

查看:100
本文介绍了OnNewText事件后何时重绘VirtualTreeView?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下代码填充VirtualStringTree并允许重命名项目:

I use this code to fill VirtualStringTree and allow renaming items:

//---------------------------------------------------------------------------
// Structure for the tree
//---------------------------------------------------------------------------
struct TVSTdata
{
UnicodeString Name;
};
//---------------------------------------------------------------------------
// Initialization of the tree
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
VirtualStringTree1->NodeDataSize = sizeof(TVSTdata);
// Fill all nodes with initial data
InitializeTree();
}
//---------------------------------------------------------------------------
// Fill all nodes with data and assign FocusedNode
//---------------------------------------------------------------------------
void TForm1::InitializeTree()
{
TVirtualNode* pNode;
TVirtualNode* pActiveNode;
TVSTdata*     pData;

VirtualStringTree1->BeginUpdate();
VirtualStringTree1->Clear();

pNode = VirtualStringTree1->AddChild(NULL); pData = static_cast<TVSTdata*>(VirtualStringTree1->GetNodeData(pNode)); pData->Name = "This is name 1";
pNode = VirtualStringTree1->AddChild(NULL); pData = static_cast<TVSTdata*>(VirtualStringTree1->GetNodeData(pNode)); pData->Name = "This is name 2";
pNode = VirtualStringTree1->AddChild(NULL); pData = static_cast<TVSTdata*>(VirtualStringTree1->GetNodeData(pNode)); pData->Name = "This is name 3"; pActiveNode = pNode;
pNode = VirtualStringTree1->AddChild(NULL); pData = static_cast<TVSTdata*>(VirtualStringTree1->GetNodeData(pNode)); pData->Name = "This is name 4";
pNode = VirtualStringTree1->AddChild(NULL); pData = static_cast<TVSTdata*>(VirtualStringTree1->GetNodeData(pNode)); pData->Name = "This is name 5";

VirtualStringTree1->Selected[pActiveNode] = true;
VirtualStringTree1->FocusedNode = pActiveNode; // PROBLEM -> if assigned from within OnNewText will still remain NULL and won't be set to pActiveNode!
VirtualStringTree1->EndUpdate();
}
//---------------------------------------------------------------------------
// Just display the text
//---------------------------------------------------------------------------
void __fastcall TForm1::VirtualStringTree1GetText(TBaseVirtualTree *Sender, PVirtualNode Node, TColumnIndex Column, TVSTTextType TextType, UnicodeString &CellText)
{
TVSTdata* pData = static_cast<TVSTdata*>(Sender->GetNodeData(Node));
CellText = pData->Name;
}
//---------------------------------------------------------------------------
// Allow editing
//---------------------------------------------------------------------------
void __fastcall TForm1::VirtualStringTree1Editing(TBaseVirtualTree *Sender, PVirtualNode Node, TColumnIndex Column, bool &Allowed)
{
Allowed = true;
}
//---------------------------------------------------------------------------
// Now this is where ideally I would reload the tree with new data - after rename
//---------------------------------------------------------------------------
void __fastcall TForm1::VirtualStringTree1NewText(TBaseVirtualTree *Sender, PVirtualNode Node, TColumnIndex Column, UnicodeString NewText)
{
NewText = "not important for this example as tree is reloaded anyway";
InitializeTree();  // ERROR is here - after assigning FocusedNode it is still NULL
//Timer1->Enabled = true; // If delayed call FocusedNode is correctly assigned and not NULL
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
//InitializeTree();
//Timer1->Enabled = false;
}
//---------------------------------------------------------------------------

问题-最初调用InitializeTree()并分配了VirtualStringTree1->FocusedNode时,已正确分配了该值(不是NULL).

The problem - when InitializeTree() is called initially and VirtualStringTree1->FocusedNode is assigned it is correctly assigned (not NULL).

但是,如果在OnNewText中调用此InitializeTree()函数实际上是在重命名事件之后从数据库中重新加载树-分配FocusedNode后,它仍然为NULL.因此很明显,无法从OnNewText事件中重新加载树并将其分配给FocusedNode.

However, if this InitializeTree() function is called within OnNewText to actually reload the tree from database after rename event - after assigning FocusedNode it is remains NULL. So obviously tree cannot be reloaded and assigned FocusedNode from within the OnNewText event.

我实现了延迟调用以重新加载新树并重新分配FocusedNode-通过实现一个快速且肮脏的计时器(可以使用PostMessage进行延迟的函数调用,但这只是一个愚蠢的示例)-在计时器内分配后,它不再NULL并按预期工作.

I implemented delayed call to reload new tree and reassign FocusedNode - by implementing a quick and dirty timer (could have used PostMessage for delayed function call but this is just a dumb example) - after assigning within a timer it no longer NULL and works as expected.

谁能指出我实现树重载的最佳方式是什么-就像使用特定事件一样,可以安全地设置新的FocusedNode并且不会将其重新分配为NULL?延迟函数调用是实现此目的的唯一方法,还是有更好的陷阱来捕获(例如,如果OnNewText之后发生,则此事件不允许设置焦点节点).当然可以,但是我对是否有更好的方法感兴趣.

Can anyone point me what is the optimal way to implement reloading of the tree - like a particular event to use in which it is safe to set new FocusedNode and it won't be reassigned back to NULL? Is delayed function call the only way to achieve this or is there a better event to trap (for example if one occurs after OnNewText if this one doesn't allow setting focused node). Of course this works but I am interested if there is a better way to do this.

推荐答案

处于tsEditing树状态时无法更改FocusedNode,直到离开OnNewText事件,您才能在那种状态. OnNewText本身更多用于编辑验证.这是事件,您可以在其中修改已编辑的值.相反,您应该使用在实际完成编辑后触发的OnEdited事件.因此,将数据库更新和树重新加载的内容移到那里,如下面的C ++ Builder伪代码所示:

You can't change the FocusedNode when you're in the tsEditing tree state and until you leave the OnNewText event, you're in that state. The OnNewText itself is more for edit validation; it is the event, where you can modify the edited value. Instead you should use the OnEdited event which is fired after the edit is actually done. So move your database update and tree reloading stuff there like shown in the following C++ Builder pseudocode:

void __fastcall TForm1::VirtualStringTree1Edited(TBaseVirtualTree *Sender, 
  PVirtualNode Node, TColumnIndex Column)
{
  // update your database here; with VirtualStringTree1.Text[Node, Column] you
  // can access the current node text after edit; when you update your DB, call
  InitializeTree();
} 

这篇关于OnNewText事件后何时重绘VirtualTreeView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆