我用這個代碼來填充VirtualStringTree並允許重命名項目:何時在OnNewText事件後重繪VirtualTreeView?
//---------------------------------------------------------------------------
// 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
分配是正確分配(NOT NULL)。
但是,如果在OnNewText
內調用此InitializeTree()
函數以在重命名事件後實際重新裝載數據庫樹 - 在指定FocusedNode
之後,它仍爲NULL。所以很顯然,樹不能從OnNewText
事件中重新加載並分配FocusedNode
。
我實現了延遲調用來重新加載新樹並重新指定FocusedNode
- 通過實現一個快速和髒的定時器(可以使用PostMessage進行延遲函數調用,但這僅僅是一個愚蠢的例子) - 在定時器之後分配它不再是NULL並按預期工作。
任何人都可以點我什麼是實現重新加載樹的最佳方式 - 就像一個特定的事件使用,其中安全設置新的FocusedNode
它不會被重新分配回NULL?延遲函數調用是實現這一目標的唯一方法,或者是否存在更好的陷阱事件(例如,如果此錯誤發生在OnNewText
之後(如果此錯誤不允許設置焦點節點)。當然這有效,但如果有更好的方法來做到這一點,我很感興趣。
如果你在談論的數據庫,你真的需要重新加載當您編輯只是一個單一節點的整個樹?當你編輯節點並重新加載數據庫中的單個行(重新加載該節點)時,難道你不想更新某一行嗎? – TLama
我需要重新排序樹,因爲編輯節點可能會改變字母順序。從排序後的數據庫中重新加載樹更容易,而不是單獨排序樹。由於加載函數也排序並創建多級樹,因此更容易這樣做。此外,在VT中進行的排序可能與數據庫的排序不同。另外,如果我重新加載只有一個節點,我仍然需要使某個節點專注於對嗎? – Coder12345
從數據庫重新加載排序數據可能會更容易,而不是排序樹,但這是一個矯枉過正的問題。如果您需要對樹進行排序,只需在節點編輯後調用'SortTree'並處理'OnCompareNodes'事件即可。對於你的問題,首先你必須記住清除樹之前選擇了哪個節點。但是你不能通過存儲'PVirtualNode'來完成,因爲當你清除並重新填充樹時,你存儲的節點指針不再有效。您必須存儲選定節點的索引。然後,在填充樹後,通過該存儲的索引找到新節點並選擇找到的節點。 – TLama