![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Господа, как можно "привязать" к TTreeNode номер записи
mmms © (2005-07-11 08:52:00)Т.е. предположим есть ветка в TTreeView "Продукты", от нее дочерние ноды "Колбаса", "Хлеб" и т.п. Нужно, чтобы юзер кликнул на "Хлеб", узнать, какой ID записи у "Хлеб", TTreeView заполняю записями из БД. Можно ли TTreeNode заполнить кроме Значениямиещё и скрытые параметры у каждого значения, например как Tagу многих компанетов, и потом, при клике на строку, определять этот параметр, а там всего цифровой код товара (по нему далее вся работа и идет).
Или, как вариант, по LIKE определять ID выбранной строки, но это лишняя нагрузка на БД, т.к. даже скольжение по TTreeView создаст множество запросов к серверу... хотя конечно, ID методом LIKE, по названию, можно не постоянно определять при скольжении, а например при двойном клике не этом товаре.
Т.е. вопрос, можно ли как то рядом с позицией в TTreeView "вбивать" ее код.
Anatoly Podgoretsky (2005-07-18 14:48:00) [41]mmms (18.07.05 14:45) [36]
Если в tv.Selected.Data ASCIIZ то приведение правильное
Ega23 (2005-07-18 14:47:00) [42]Блин, ты сначала разберисть, что ты в tv.Selected.Data раньше положил. В каком виде?
mmms (2005-07-18 14:45:00) [43]Удалено модератором
mmms (2005-07-18 14:45:00) [44]Анатолий, так я понял, я с утра хочу спросить, как верный то написать :(
Showmessage(PChar(tv.Selected.Data));
Anatoly Podgoretsky (2005-07-18 14:34:00) [45]У тебя указатель не верный!
mmms (2005-07-18 14:31:00) [46]EAccessViolation
'Access violation at address ...'
evvcom (2005-07-18 14:08:00) [47]
> почему так ошибку выдает
Что за ошибка? Неужели влом написать?
> ... и по TStringList делать сравнение в условии, да что
> то не сравнивается
Ну долго мы в телепатов будем играть? Ну прям Пельш новоиспеченный с игрой "Угадай, мою писанину!"
mmms (2005-07-18 13:57:00) [48]Ega23
Хорошо, почему так ошибку выдает, что я не так пишу? (прошу извинить за такие вопросы)
procedure TForm1.tvClick(Sender: TObject);
begin
Showmessage(PChar(tv.Selected.Data));
end;
evvcom
Ну да, сейчас пишется ссылка на Integer, я хотел вместо этого Integer TStringList хранить, текст типа 'fdfg'+#13#10+'fdgfgfg'... и по TStringList делать сравнение в условии, да что то не сравнивается, и в итоге кроме одного итема на Tree больши ничего нет, что и логично. Но это заморочки мои, мне надо всего лишь записать + вытащить число в Data. Был бы Tag, как бы хорошо было :) То что тут код был.. он конечно хорош, но процедура [2] мне очень подходит, осталось только достать Data.
evvcom (2005-07-18 11:35:00) [49]
> Я просто туда буду писать 2 строки
Это как? В Pointer можно записать только один указатель. Неважно на что: string, char, integer или вообще на мусор. Важно, как этот указатель будешь потом интерпретировать.
> Как будто String не сравнивается
В [2] никаких указателей на string я не увидел, поэтому делать какие-то выводы просто не из чего.
Ega23 (2005-07-18 11:28:00) [50]Читай про PChar
mmms (2005-07-18 11:26:00) [51]Послать к книге понятно, проще всего, я понять не могу, как через указатель, прочитать значение. В данном случае это нетипизированный указатель, который может указывать на данные произвольного типа. Видимо не туда "обращаюсь" чтобы прочитать данные...
И 2й вопрос, можно ли запихнуть в коде
[2] mmms (11.07.05 09:00)
Data типа String. Я просто туда буду писать 2 строки, вместо теперешноего одного числа. Вопрос в том, что делая это, у меня не происходит "отрисовки меню", т.е. дальше строки
if Tree.Items.Item[i].Data = Pointer(Query.FieldByName(idParent).asString)
Как будто String не сравнивается...
Anatoly Podgoretsky (2005-07-18 10:56:00) [52]Ega23 © (18.07.05 10:46) [27]
Не царское дело!
Ega23 (2005-07-18 10:46:00) [53]Слушай, может ты сначала какую-нибудь книжку почитаешь? Про типы данных, например? Про указатели? Про классы?
Чтобы вот с таим-вот Showmessage(PString(tv.Selected.Data)^) не позориться?
mmms (2005-07-18 10:25:00) [54]Делаю так, ошибка:
procedure TForm1.tvClick(Sender: TObject);
begin
Showmessage(PString(tv.Selected.Data)^);
end;
mmms (2005-07-18 10:24:00) [55]Приветствую всех!
Снова с TreeView,
Код от mmms (11.07.05 09:00)
Как можно узнать вот это Pointer(Query.FieldByName(idNode).asInteger)значение, например в Showmessage('');, т.е. привести к string.
Ega23 (2005-07-11 16:27:00) [56]2 Андрей Жук © (11.07.05 16:20) [23]
Я бы на твоём месте вот сюда
// заповнимо дерево
with DataSet do
begin
LastNode := nil;
First;
while not Eof do
ещё DisableControls поставил (в конце - EnableControls).
Андрей Жук (2005-07-11 16:20:00) [57]
{
Формат елементів усіх дерев
mem_id - обовязково. Ідентифікатор елемента
mem_pid - обовязково. Ідентифікатор "батьківського" елемента
is_leaf - обовязково. Ознака, чи є елемент елементом нижнього рівня
outlevel - обовязково. Рівень елемента
mem_order - обовязково. Порядковий номер в структурі
mem_name - обовязково. Назва елемента
mem_desc - обовязково. Описання елемента
mem_type - не обовязково. Тип елемента
}
type
TMyTreeNodes = record
mem_id: integer;
mem_pid: integer;
is_leaf: boolean;
outlevel: integer;
mem_order: integer;
mem_name: string;
mem_desc: string;
mem_type: string;
changing: boolean; // чи змінювалися дані в обєкті
inserting: boolean; //чи є обєкт доданим (без відображення в базі)
ParentNode: TTreeNode;
end;
PTMyTreeNodes = ^TMyTreeNodes;
function GenerateTree(Tree: TTreeView; DataSet: TDataSet): TFunctionResult;
var
FunctionResult: TFunctionResult;
vData: PTMyTreeNodes;
Node, LastNode: TTreeNode;
begin
Result.Successful := false;
// якщо дерево чи датасет не ініціалізовані, зупинити виконання
if not Assigned(Tree) or not Assigned(DataSet) then
begin
Result.MessageOnError := 'Programmer error - not initilized objects on creating tree';
Exit;
end;
// якщо датасет не активний, то зупинити виконання
if not DataSet.Active then
begin
Result.MessageOnError := 'Programmer error - not activated Dataset';
Exit;
end;
// очистимо дерево, якщо помилка зупинити виконання
try
LockWindowUpdate(Tree.Parent.Handle);
FunctionResult := ClearTree(Tree);
if not FunctionResult.Successful then
begin
Result.MessageOnError := FunctionResult.MessageOnError;
Exit;
end;
// заповнимо дерево
with DataSet do
begin
LastNode := nil;
First;
while not Eof do
begin
New(vData); // створимо елемент
with vData^ do
begin
// заповнюємо його поля
try
mem_id := FindField('mem_id').AsInteger;
mem_pid := FindField('mem_pid').AsInteger;
is_leaf := boolean(FindField('is_leaf').AsInteger);
outlevel := FindField('outlevel').AsInteger;
mem_order := FindField('mem_order').AsInteger;
mem_name := FindField('mem_name').AsString;
mem_desc := FindField('mem_desc').AsString;
if Assigned(FindField('mem_type')) then
mem_type := FindField('mem_type').AsString
else
mem_type := 'general';
changing := false;
inserting := false;
except on E: Exception do
begin
Result.MessageOnError := 'Programm error - incompatible structure' + #10#13 + 'Details: ' + E.Message;
Exit;
end;
end;
// якщо це елемент верхнього рівня, то додамо його в корінь
if vData.outlevel = 1 then
begin
Node := Tree.Items.Add(nil, vData^.mem_desc);
vData.ParentNode := nil;
end
// якщо елемент нижчого рівня, то додати як "сина"
else if PTMyTreeNodes(LastNode.Data)^.outlevel < vData.outlevel then
begin
Node := Tree.Items.AddChild(LastNode, vData^.mem_desc);
vData.ParentNode := LastNode;
end
// якщо елемент одного рівня, то додати як "брата"
else if PTMyTreeNodes(LastNode.Data)^.outlevel = vData.outlevel then
begin
Node := Tree.Items.AddChild(LastNode.Parent, vData^.mem_desc);
vData.ParentNode := LastNode.Parent;
end
// якщо елемент вищогого рівня, то знайти "підходящого батька" та додати як "сина"
else if PTMyTreeNodes(LastNode.Data)^.outlevel > vData.outlevel then
begin
while PTMyTreeNodes(LastNode.Data)^.outlevel >= vData.outlevel do
LastNode := LastNode.Parent;
Node := Tree.Items.AddChild(LastNode, vData^.mem_desc);
vData.ParentNode := LastNode.Parent;
end;
// занесення даних до структури
Node.Data := vData;
LastNode := Node;
Next;
end;
end;
end;
Result.Successful := true;
finally
LockWindowUpdate(0);
end;
end;
Ega23 (2005-07-11 11:39:00) [58]
unit uKdrDBTreeView;
interface
uses Windows, SysUtils, Classes, comctrls, stdctrls, db, graphics, controls,
Dialogs, contnrs;
Type
TCustomKdrDBTreeView=class;
TKdrDBTreeViewItemIdent = class(TObject)
private
FParentKeyFieldValue: Variant;
FKeyFieldValue: Variant;
FDisplayFieldValue: String;
FImageFieldValue: Integer;
FNode: TTreeNode;
public
property KeyFieldValue:Variant Read FKeyFieldValue Write FKeyFieldValue;
property ParentKeyFieldValue:Variant Read FParentKeyFieldValue Write FParentKeyFieldValue;
property DisplayFieldValue:String Read FDisplayFieldValue Write FDisplayFieldValue;
property ImageFieldValue:Integer Read FImageFieldValue Write FImageFieldValue;
property Node:TTreeNode Read FNode Write FNode;
end;
TTreeDataLink = class(TDataLink)
private
FTree: TCustomKdrDBTreeView;
FMinParent: Integer;
FMinValue: Integer;
public
constructor Create(ATree:TCustomKdrDBTreeView);
procedure DataSetChanged; override;
procedure ActiveChanged; override;
property MinParent:Integer Read FMinParent Write FMinParent;
property MinValue:Integer Read FMinValue Write FMinValue;
end;
TCustomKdrDBTreeView = class(TCustomTreeView)
private
FDataLink: TTreeDataLink;
FTreeItems:TObjectList;
FKeyField: String;
FDisplayField: String;
FParentField: String;
FDataSource: TDataSource;
Inh_TVChange: TTVChangedEvent;
procedure SetFDataSource(const Value: TDataSource);
protected
function LocateByNode(Node:TTreeNode):Boolean;
procedure TVChange(Sender: TObject; Node: TTreeNode);
procedure AddAllNodes(ParentID: Integer; ParentNode:TTreeNode);
function SetSelectedNode(const Value:Variant):TTreeNode;
property DataSource:TDataSource Read FDataSource Write SetFDataSource;
property DisplayField:String Read FDisplayField Write FDisplayField;
property KeyField:String Read FKeyField Write FKeyField;
property ParentField:String Read FParentField Write FParentField;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Clear;
procedure DataChanged;
procedure ActiveChanged;
function AddItem:Integer;
end;
TKdrDBTreeView = class (TCustomKdrDBTreeView)
published
property DataSource;
property DisplayField;
property KeyField;
property ParentField;
end;
implementation
{ TTreeDataLink }
//*****************************************************************************
procedure TTreeDataLink.ActiveChanged;
var
i:Integer;
begin
inherited;
FTree.Clear;
if (DataSet.Active) and (FTree<>nil) and (dsBrowse in [DataSet.State]) then
begin
BufferCount:=DataSet.RecordCount;
i:=0;
ActiveRecord:=i;
MinParent:=DataSet.FieldByName(FTree.KeyField).Value;
MinValue:=DataSet.FieldByName(FTree.ParentField).Value;
While (i<BufferCount) do
begin
FTree.AddItem;
With DataSet do
begin
if MinValue>FieldByName(FTree.KeyField).AsInteger then
MinValue:=FieldByName(FTree.KeyField).AsInteger;
if MinParent>FieldByName(FTree.ParentField).AsInteger then
MinParent:=FieldByName(FTree.ParentField).AsInteger;
end;
Inc(i);
ActiveRecord:=i;
end;
FTree.ActiveChanged;
ActiveRecord:=0;
end;
end;
//*****************************************************************************
constructor TTreeDataLink.Create(ATree: TCustomKdrDBTreeView);
begin
inherited Create;
FTree:=ATree;
VisualControl:=True;
end;
Ega23 (2005-07-11 11:39:00) [59]
//*****************************************************************************
procedure TTreeDataLink.DataSetChanged;
begin
inherited;
if (DataSet.Active) and (FTree<>nil) and (dsBrowse in [DataSet.State]) then
FTree.DataChanged;
end;
//*****************************************************************************
{ TKdrDBTreeView }
procedure TCustomKdrDBTreeView.ActiveChanged;
begin
Items.BeginUpdate;
AddAllNodes(FDataLink.MinParent, nil);
Items.EndUpdate;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.AddAllNodes(ParentID: Integer;
ParentNode: TTreeNode);
var
k:Integer;
CurrNode:TTreeNode;
begin
for k:=0 to FTreeItems.Count-1 do
begin
With TKdrDBTreeViewItemIdent(FTreeItems.Items[k]) do
begin
if (Node<>nil) or (ParentKeyFieldValue<>ParentID) then Continue;
if ParentNode=nil then
CurrNode:=Items.Add(nil, DisplayFieldValue)
else
CurrNode:=Items.AddChild(ParentNode, DisplayFieldValue);
CurrNode.ImageIndex:=ImageFieldValue;
CurrNode.SelectedIndex:=ImageFieldValue;
Node:=CurrNode;
CurrNode.Data:=FTreeItems.Items[k];
AddAllNodes(KeyFieldValue, CurrNode);
end; // With
end; // for
end;
//*****************************************************************************
function TCustomKdrDBTreeView.AddItem: Integer;
var
i:Integer;
begin
try
i:=FTreeItems.Add(TKdrDBTreeViewItemIdent.Create);
With TKdrDBTreeViewItemIdent(FTreeItems.Items[i]) do
begin
KeyFieldValue:=FDataLink.DataSet.FieldByName(KeyField).Value;
ParentKeyFieldValue:=FDataLink.DataSet.FieldByName(ParentField).Value;
DisplayFieldValue:=FDataLink.DataSet.FieldByName(DisplayField).AsString;
end;
except
Result:=-1;
end;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.Clear;
var
i:Integer;
begin
FTreeItems.Clear;
Items.Clear;
end;
//*****************************************************************************
constructor TCustomKdrDBTreeView.Create(AOwner: TComponent);
begin
inherited;
HideSelection:=False;
FDataLink:=TTreeDataLink.Create(Self);
FTreeItems:=TObjectList.Create(True);
if Assigned(Self.OnChange) then Inh_TVChange:=Self.OnChange;
Self.OnChange:=TVChange;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.DataChanged;
begin
Selected:=SetSelectedNode(FDataLink.DataSet.FieldByName(KeyField).AsInteger);
end;
//*****************************************************************************
destructor TCustomKdrDBTreeView.Destroy;
begin
FTreeItems.Free;
FDataLink.Free;
inherited;
end;
//*****************************************************************************
function TCustomKdrDBTreeView.LocateByNode(Node: TTreeNode): Boolean;
var
i:Integer;
V:Variant;
keyFields:String;
begin
Result:=False;
for i:=0 to FTreeItems.Count-1 do
if TKdrDBTreeViewItemIdent(FTreeItems.Items[i]).Node=Node then
begin
V:=VarArrayCreate([0,1], varVariant);
V[0]:=TKdrDBTreeViewItemIdent(FTreeItems.Items[i]).KeyFieldValue;
V[1]:=TKdrDBTreeViewItemIdent(FTreeItems.Items[i]).ParentKeyFieldValue;
keyFields:=KeyField+';'+ParentField;
Result:=FDataLink.DataSet.Locate(KeyFields,V , []);
end;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.SetFDataSource(const Value: TDataSource);
begin
if (Value<>nil) and (FDataSource<>Value) then
begin
FDataSource := Value;
FDataLink.DataSource:=Value;
end;
end;
//*****************************************************************************
function TCustomKdrDBTreeView.SetSelectedNode(
const Value: Variant): TTreeNode;
var
i:Integer;
begin
Result:=nil;
for i:=0 to FTreeItems.Count-1 do
With TKdrDBTreeViewItemIdent(FTreeItems.Items[i]) do
if KeyFieldValue=Value then
begin
Result:=Node;
Break;
end;
end;
//*****************************************************************************
procedure TCustomKdrDBTreeView.TVChange(Sender: TObject; Node: TTreeNode);
begin
LocateByNode(Node);
if (@Inh_TVChange<>nil) then Inh_TVChange(Sender, Node);
end;
//*****************************************************************************
end.
mmms (2005-07-11 11:37:00) [60]
[18] msguns © (11.07.05 11:33)
Да ничего, хорошо, посмотрю как у других это делается :)