在SQL中有两个表对应DELPHI中的Treeview及Dbgrid,我想单击treeview中的节点,则dbgrid中显示相关联和记录,请帮我分析一下,有源码较好,TKS!

解决方案 »

  1.   

    TO:lgqTiger(我爱Delphi),我再说详细点。
      我有一个物料类别表MaterielType(no,parentno,name)用于treeview之数据
      物料名称表Materiel(m_no,no…),作为Dbgrid的数据表
      其中物料名称表中的no与物料类别表的no有对应关系
      
      1.如何使物料名称表和物料类别表联接起来,比喻选中物料类型表中的某一条记录,则可以看到相应类别的物料名称
      2.如何实现treeview与dbgrid联接,如选中treeview中的某节点物料类别时,则Dbgrid中显示相应类别的物料名称请帮手,TKS!
      

  2.   

    先把表 添加到treeview中 然后判断点击的 节点
    做相应处理引passos(古月春秋) :表结构可以采用两种方式:
    1、编码方式,采用001001001的字符串,然后按照每级的长度切开,然后建树。这种方法最慢,而且树的层次数有限。
    2、链式存储方式。结构是 节点编号、父节点编号、名称、编码... 这种方法是最好的解决方法。我详细说一下:
    关键是两个编号字段,顶级接点的编号可以是-1或者其他特殊值(字段类型用数字或者字符串都可以)。比如树形是
    A----B
      |--C
      |--D----E
           |--F那么数据库内容是:
    节点编号 父节点编号 名称
    1         -1          A
    2         1           B
    3         1           C
    4         1           D
    5         4           E
    6         4           F
    建立树的操作可以使用一个先根顺序建立各个节点(实际上是一个递归函数,广度优先),算法如下://建立一个记录,存储树节点的信息
      PNodeData = ^TNodeData;
      TNodeData = record
        ID, ParentID: LongInt;
        Text: ShortString;
      end;//ParentTreeNode TreeView父节点
    //ParentID 父节点编号
    //TreeDataSet 存储该树的数据表、之前要打开
    procedure BuildTree(ParentNode: TTreeNode; ParentID: Integer);
    var
      I: Integer;
      ANodeData: PNodeData;
      NewNode: TTreeNode;
    begin
      //过滤出该父节点下的子节点
      TreeDataSet.Filter := Format('父节点编号 = %d', [ParentID]);
      TreeDataSet.Filtered := True;
      
      for I := 0 to TreeDataSet.RecordCount - 1 do
      begin
        ANodeData := New(PNodeData);
        ANodeData^.ID := TreeDataSet.FieldValues['节点编号'];
        ANodeData^.ParentID := TreeDataSet.FieldValues['父节点编号'];
        ANodeData^.Text := TreeDataSet.FieldValues['名称'];
        NewNode := TreeView.AddChild(ParentNode, ANodeData^.Text);
        NewNode.Data := ANodeData;
        Next;
      end;  //递归调用本函数,为各个子节点生成树
      //很明显,如果当前节点没有子节点,那么就是递归调用的结束条件了
      //这里的判断是检查第一次调用传进来的参数,如果是nil就用TreeView的属性来访问
      if Assigned(ParentNode) then
      begin
        for I := 0 to ParentNode.Count - 1 do
          BuildTree(ParentNode.Item[I], PNodeData(ParentNode.Item[I].Data)^.ID);
      else begin
        for I := 0 to TreeView.Items.Count - 1 do
          BuildTree(TreeView.Items[I], PNodeData(TreeView.Items[I].Data)^.ID);
      end;
    end;
    初始的调用方法是
    TreeDataSet.Open;BuildTree(TreeView.Add(nil, '树根'), -1);//或者 BuildTree(nil, -1);TreeDataSet.Close;
    TreeDataSet.Filter := '';
    TreeDataSet.Filtered := False;
    上面那段代码在程序退出的时候要记得释放每个树节点的data指针占用的内存,DELPHI不会负责释放那些空间的。如果不做,将导致内存泄露。
    再多加一点注释:
      //把数据库中查询出来的每个节点加入到ParentNode下
      for I := 0 to TreeDataSet.RecordCount - 1 do
      begin
        //为节点分配一个记录,记录节点的ID等信息
        ANodeData := New(PNodeData);
        //记录该节点的各个属性,后面要用到
        ANodeData^.ID := TreeDataSet.FieldValues['节点编号'];
        ANodeData^.ParentID := TreeDataSet.FieldValues['父节点编号'];
        ANodeData^.Text := TreeDataSet.FieldValues['名称'];
        NewNode := TreeView.AddChild(ParentNode, ANodeData^.Text);    //把该节点的DATA指针指向这个记录
        NewNode.Data := ANodeData;    //继续添加下一个节点
        Next;
      end;
      如果不执行下面的代码,那么就只生成一级的树,否则就生成全部的树。按照你的问题的要求,去掉下面的代码,在每次点一个+号的时候调用BuildTree就可以了。  if Assigned(ParentNode) then
      begin
        for I := 0 to ParentNode.Count - 1 do
          BuildTree(ParentNode.Item[I], PNodeData(ParentNode.Item[I].Data)^.ID);
      else begin
        for I := 0 to TreeView.Items.Count - 1 do
          BuildTree(TreeView.Items[I], PNodeData(TreeView.Items[I].Data)^.ID);
      end;
      

  3.   

    TO:duxin(小伍) 我不太了解指针啊,可不可以不用指针啊?TKS!
      

  4.   

    干吗要用指针,在treeview的onchange里面用query.locate()就可以.很简单,速度也快.
      

  5.   

    对了,我说详细一些,比如主表示ADOQuery1,从表是ADOQuery2,设置ADOQuery2的datasource为datasource1,SQL语句为'select * from table_name where key=:key',首先将ADOQuery1的值添加到treeview1中,当treeview1.onchange的时候,用ADOQuery1.locate来定位主表的记录,这样从表的值会自动筛选。然后显示到DBGrid中就可以了。
      

  6.   

    不会指针,不能学呀
    试着用它,等你做完了这个难题,你会发现
    你对指针有更多的了解。你也会从更深的角度来
    看delphi。恭喜你,你对delphi的了解又精进了
    一层。