-->

何时OnNewText事件后重绘VirtualTreeView?(When to redraw Vi

2019-09-24 02:18发布

我用这个代码来填充VirtualStringTree并允许重命名项目:

//---------------------------------------------------------------------------
// 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)。

但是,如果此InitializeTree()函数被调用内OnNewText实际上从数据库重新加载树后改名事件-后分配FocusedNode它仍然是NULL。 所以很明显树不能被重新加载并分配FocusedNode从内OnNewText事件。

我实现延迟调用加载新的树和重新分配FocusedNode -通过实施快速和肮脏的定时器(也可以使用PostMessage作为延迟函数调用,但是这仅仅是一个愚蠢的例子) -一个定时器不再NULL内分配后按预期工作。

任何人都可以点我什么是执行树的重新加载的最佳方式-就像一个特定事件来使用,它是安全的,设置新的FocusedNode ,它不会被重新调回为NULL? 延迟函数调用来实现这一目标的唯一途径还是有更好的事件陷阱(例如,如果一个发生后OnNewText如果一个不允许设置聚焦节点)。 当然,这工作,但我很感兴趣,如果有更好的方法来做到这一点。

Answer 1:

你不能改变FocusedNode当你在tsEditing树的状态,直到你离开OnNewText事件,你在那个状态是。 该OnNewText本身则多为编辑验证; 这是事件,在那里你可以修改编辑的值。 相反,你应该使用OnEdited后的编辑实际完成其触发事件。 因此,移动你的数据库更新和树重装的东西有一样显示在下面的C ++ Builder的伪代码:

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();
} 


文章来源: When to redraw VirtualTreeView after OnNewText event?