olegenty |
Отправлено: 25.10.2006, 11:01 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
После сортировки пропадает инициирующая информация об узлах, инициированных, как vsHasChildren, пропадает раскрывающий крестик, если фактически узел ни разу не раскрывался...
Пока тупо заглушил созданием фиктивного Child. Но это есть хероватое решение, хочется чего-то большого и тёплого, например — совета...
|
|
Doga |
Отправлено: 25.10.2006, 16:03 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Привет!
Странно, у меня такого эффекта не наблюдается...
Проверил на том самом пресловутом VTVDemo. Для главной формы был добавлен следующий код:
VTreeHolder.h
CODE |
class TNodeData : public TObject
{
//...
public:
//...
__property AnsiString NodeText = {read = FNodeText};
__property AnsiString NodeHint = {read = FNodeHint};
//...
}
|
MonitorForm.h
CODE |
class TMonitorForm : public TForm
{
//...
private: // User declarations
//...
TSortDirection SortDirection;
//...
}
|
MonitorForm.cpp
CODE |
//---------------------------------------------------------------------------
__fastcall TMonitorForm::TMonitorForm(TComponent* Owner)
: TForm(Owner)
{
//...
SortDirection = sdDescending;
}
//---------------------------------------------------------------------------
//Обработчик события сравнения нодов
void __fastcall TMonitorForm::VirtualStringTree1CompareNodes(
TBaseVirtualTree *Sender, PVirtualNode Node1, PVirtualNode Node2,
TColumnIndex Column, int &Result)
{
if (Node1->Parent == Node2->Parent)
{
VTVNODEDATA *VTVNodeData1 = (VTVNODEDATA *)VirtualStringTree1->GetNodeData(Node1);
VTVNODEDATA *VTVNodeData2 = (VTVNODEDATA *)VirtualStringTree1->GetNodeData(Node2);
if (VTVNodeData1 && VTVNodeData2)
{
Result = VTVNodeData1->NodeData->NodeText.AnsiCompare(VTVNodeData2->NodeData->NodeText);
}
else
{
Result = 0;
}
}
else
{
Result = 0;
}
}
//---------------------------------------------------------------------------
//Обработчик события OnClick дополнительной кнопки сортировки
void __fastcall TMonitorForm::BitBtn2Click(TObject *Sender)
{
if (SortDirection == sdDescending)
{
SortDirection = sdAscending;
}
else
{
SortDirection = sdDescending;
}
VirtualStringTree1->SortTree(0, SortDirection, false);
}
//---------------------------------------------------------------------------
|
Отредактировано Doga — 25.10.2006, 17:19
|
|
olegenty |
Отправлено: 26.10.2006, 09:24 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
а были ли у тебя там ноды со Styles vsHasChildren фактически без этих самых Children?
вся фишка в том, что не делаю я ничего "неправомерного".
вот так сравниваю:
CODE |
///////////////////////////////////////////////////////////////////////////////////////////////////
//
void __fastcall COperator::OnCompareNodes( TBaseVirtualTree *Sender
, PVirtualNode Node1
, PVirtualNode Node2
, TColumnIndex Column
, int &Result
)
{
RecordType *Record1 = static_cast<RecordType*>(Sender->GetNodeData(Node1));
RecordType *Record2 = static_cast<RecordType*>(Sender->GetNodeData(Node2));
AnsiString SortGroup1 = Records_[Record1->InstanceID()]["SortGroup"] + Records_[Record1->InstanceID()]["Design"];
AnsiString SortGroup2 = Records_[Record2->InstanceID()]["SortGroup"] + Records_[Record2->InstanceID()]["Design"];
Result = AnsiCompareStr(SortGroup1, SortGroup2);
}
|
вот так сортирую
CODE |
///////////////////////////////////////////////////////////////////////////////////////////////////
//
void __fastcall COperator::OnHeaderClick( TVTHeader *Sender
, TColumnIndex Column
, TMouseButton Button
, TShiftState Shift
, int X
, int Y
)
{
if (mbLeft == Button && !Column)
{
if (sdAscending == Sender->SortDirection)
{
Sender->SortDirection = sdDescending;
} else
{
Sender->SortDirection = sdAscending;
}
Tree_->SortTree(0, Sender->SortDirection);
}
}
|
а вот так инициализирую:
CODE |
void __fastcall COperator::OnInitNode( TBaseVirtualTree *Sender
, PVirtualNode ParentNode
, PVirtualNode Node
, TVirtualNodeInitStates &InitialStates
)
{
RecordType *Record = static_cast<RecordType*>(Sender->GetNodeData(Node));
if (Record)
{
if (Record->HasSpec())
{
Node->States << vsHasChildren;
InitialStates << ivsHasChildren;
}
}
}
|
так вот, после вызова метода SortTree в любом месте, происходит сброс States. по крайней мере, оттуда пропадает vsHasChildren, и, что самое непонятное, даже ReinitNode для всех узлов после сортировки ни к чему не приводит, хотя код инициализации и вызывается. (хотя, ReinitNode — это хуже, чем та заглушка, что я пока прикрутил).
|
|
Doga |
Отправлено: 26.10.2006, 14:23 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Привет!
QUOTE |
а были ли у тебя там ноды со Styles vsHasChildren фактически без этих самых Children?
|
Да, конечно. В VTVDemo все ноды такие. Нода ничего не знает о своих будущих детках до события OnExpanding. По этому я так же как и ты устанавливаю флаг состояния vsHasChildren принудительно.
Правда инициализация ноды у меня происходит немного по другому. Я неиспользовал событие OnInitNode, поскольку мне это было неудобно. Инициализация ноды производится сразу за её добавлением (созданием) в одном блоке кода. Тогда же производится и установка флага vsHasChildren. Хотя я, не думаю, что всё это имеет какое либо значение.
Я думаю, тут всё дело в способе взова метода SortTree.
procedure SortTree(Column: TColumnIndex; Direction: TSortDirection; DoInit: Boolean = True);
А именно, в последнем третьем параметре — DoInit. Похоже он отвечает за принудителную переинициализацию сортируемых нодов. Если его проигнорировать при вызове SortTree
(т.е. типа SortTree(0, SortDirection); ),
оставив его равным по умолчанию TRUE, тогда, признаюсь, и уменя сбрасываются флаги vsHasChildren (тоолько что проверил ).
А если его принудительно установить как FALSE
(т.е. типа SortTree(0, SortDirection, false); ),
то все работает как надо! Сам этого раньше не знал
|
|
olegenty |
Отправлено: 26.10.2006, 15:01 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
я инициализировал тоже по-разному.
твой рецепт — что доктор прописал. я и не подумал посмотреть описание метода SortTree, выдрав всё из примера, где параметр опущен.
Спасибо! (ибо моя заглушка спасала меня только с vsHasChildren, но не с vsMultiline)
Наирульнейшее дерево!!!
|
|
Doga |
Отправлено: 26.10.2006, 16:02 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Ну что ж, это хорошо
Я вообще то, когда у себя проверял, список параметров для SortTree получил через Class Explorer и их значения выставлял интуитивно по названиям параметров . И, естественно не знал, что третий параметр имеет значение по умолчанию. Подозрение возникло, когда сравнил наши вызовы этого метода
|
|
olegenty |
Отправлено: 26.10.2006, 16:34 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
грабля имеет продолжение: редактирование нода приводит к его переинициализации. и никаких скрытых переметров не обнаружено (в методе EditNode). щас буду искать способ лечения. у меня дерево редактируемое самописными редакторами по самое нехочу. пока вернулся к старой заглушке.
непонятно следующее: после редактирования происходит переинициализация. в ней я корректно заполняю States (OnInitNode), и вижу, что vsHasChildren присутствует в States, однако ещё где-то/как-то потом этот параметр сбрасывается. пймать бы, где и как. хоть в сорцы лезь. кстати, так и сделаю, наверное...
|
|
Doga |
Отправлено: 26.10.2006, 17:51 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Я так понимаю, ты хочешь отредактировать дополнительные данные хранимые в свойстве Data ноды.
Для этого, я думаю, EditNode можно и не вызывать. Запускай свой редактор, а потом просто обнови ноду (InvalidateNode), да и это нужно будет только в случае изменения текста самой ноды.
А для редактирования одного лишь текста самой ноды достаточно события OnNewText.
|
|
olegenty |
Отправлено: 27.10.2006, 06:09 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
всё хуже намного: самописный редактор (суть — реализация COM-интерфейса) инициализируется в OnCreateEditor. это регламентируется TVirtualStringTree. Редактирую не только текст, редактирую всё, что не лень. И вот ввиду регламента TVirtualStringTree я привязан к его событиям, определющим редактирование. т.е. без EditNode никак.
событие OnInitChildren не спасает.
|
|
Doga |
Отправлено: 27.10.2006, 14:02 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Блин, даже не знаю, что ещё предложить
Может, на форуме softgems'a посмотреть?
|
|
olegenty |
Отправлено: 27.10.2006, 14:31 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
пофигу. сорец дерева ещё не разобрал, но проверил — баг затрагивает только vsHasChildren, поэтому заглушки с фиктивным Child хватит вполне. на чтение форума особо времени нет, к утру бы сдать уже кусочек на тестирование... а том только эта проблема. в общем — всё в пределах допустимых отклонений.
|
|
Doga |
Отправлено: 27.10.2006, 14:45 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
QUOTE |
в общем — всё в пределах допустимых отклонений.
|
Ну, это как всегда
|
|
Doga |
Отправлено: 31.10.2006, 20:43 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
Привет!
Ну что, решение найти удалось? Самому интересно
|
|
olegenty |
Отправлено: 01.11.2006, 07:42 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
Нет, всё осталось с заглушкой. Но я и не искал решения, отдал заказчику Wizard, пока не звонит — значит всё в порядке. Дело в том, что программирую я конечно планово, но в промежутках между выполнением основных функций — руководства группой программистов и сервисных работников. И только по одному направлению, которое полностью висит на мне (в наследство от самого себя). Так вот, пока заказчик не звонит, я занят работой, очень отличной от программирования. И разберусь теперь уже только если будут какие-то конкретные проблемы у пользователей подразделения заказчика.
|
|