Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Господа, как можно "привязать" к TTreeNode номер записи


Страницы:   1 2 3 4

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)
Да ничего, хорошо, посмотрю как у других это делается :)


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо