表是这样设计的 
PROCLASSID 类别ID 
PROCLASSNAME 类别名称 
PROFCLASSID 上级类别 值是这样保存的: 
类别ID      类别名称   上级类别 
53          1111      
54          2222     53 
55          3333     54 
56          444      55 这样的树该怎么写啊?sos!!!数据值不能修改 

解决方案 »

  1.   

    有必要的话可以建个抽象层:TCategory = class
    //...
    end;ICategoryRepository = interface
      function FindCategory(id: Integer): TCategory;
      function FindCategories(category: TCategory): TCategoryList;
      // procedure Add, Remove, etc.
    end;再实现接口
    TCategoryRepository = class(TInterfacedObject, ICategoryRepository)
    private
      fDataSet: TDataSet;  // 比如类别是存在数据集里面的
    public
      constructor Create(dataSet: TDataSet); // 通过构造器传入
    //...
      function FindCategory(id: Integer): TCategory;
      function FindCategories(category: TCategory): TCategoryList;
    //...
    end;具体实现其实很简单的。
      

  2.   

    粉比较多,还开两贴,花时间写了一个函数procedure BuildTree(TreeView: TTreeView; DataSet: TDataSet;
      KeyField, ParentField, TitleField: string);
    { 高效建树过程 by blazingfire 2008-05-21 }
    type
      PNodeData = ^TNodeData;
      TNodeData = record
        Key: Integer;
        Parent: Integer;
        Title: string;
        Node: TTreeNode;
      end;  function CompareKey(Item1, Item2: Pointer): Integer;
      begin
        Result := PNodeData(Item1)^.Key - PNodeData(Item2)^.Key;
      end;  function BisearchNodeData(Key: Integer; SortedList: TList): PNodeData;
      var
        Lo, Hi, Mid: Integer;
      begin
        Lo := 0;
        Hi := SortedList.Count - 1;
        while Lo <= Hi do
        begin
          Mid := (Lo + Hi) div 2;
          Result := SortedList[Mid];
          if Key > Result^.Key then
            Lo := Mid + 1
          else if Key < Result^.Key then
            Hi := Mid - 1
          else
            Exit {至此已经找到};
        end;
        Result := nil;
      end;  procedure BuildNode(nData: PNodeData; SortedList: TList);
      var
        ParentData: PNodeData;
      begin
        if nData^.Node = nil then
        begin
          //折半查找父级PNodeData
          ParentData := BisearchNodeData(nData^.Parent, SortedList);
          //父级为空或是本身,就建一个根节点
          if (ParentData = nil) or (ParentData = nData) then
            nData^.Node := TreeView.Items.AddChild(nil, nData^.Title)
          else
          begin
            if ParentData.Node = nil then
              BuildNode(ParentData, SortedList);
            nData^.Node := TreeView.Items.AddChild(ParentData.Node, nData^.Title);
          end;
        end;
      end;var
      List, SortedList: TList;
      i: Integer;
      nData: PNodeData;
      fldKey, fldParent, fldTitle: TField;
    begin
      TreeView.Items.BeginUpdate;
      List := TList.Create;
      try
        fldKey := DataSet.FieldByName(KeyField);
        fldParent := DataSet.FieldByName(ParentField);
        fldTitle := DataSet.FieldByName(TitleField);
        TreeView.Items.Clear;    DataSet.DisableControls;
        try
          //把数据集的数据加载到内存,以备在内存里建树
          DataSet.First;
          while not DataSet.Eof do
          begin
            New(nData);
            nData^.Key := fldKey.AsInteger;
            nData^.Parent := fldParent.AsInteger;
            nData^.Title := fldTitle.AsString;
            nData^.Node := nil;
            List.Add(nData);
            DataSet.Next();
          end;
        finally
          DataSet.EnableControls;
        end;    SortedList := TList.Create;
        try
          SortedList.Assign(List);
          SortedList.Sort(@CompareKey); //以Key排序,以备用折半查找
          for i := 0 to List.Count - 1 do
            BuildNode(List[i], SortedList);
        finally
          SortedList.Free;
        end;
      finally
        TreeView.Items.EndUpdate;
        for i := 0 to List.Count - 1 do
          Dispose(List[i]);
        List.Free;
      end;
    end;
    调用例子:procedure TForm1.Button1Click(Sender: TObject);
    begin
      ADOQuery1.Close;
      ADOQuery1.SQL.Text := 'SELECT PROCLASSID,PROFCLASSID,PROCLASSNAME from TableName';
      ADOQuery1.Open;
      BuildTree(TreeView1, ADOQuery1, 'PROCLASSID', 'PROFCLASSID', 'PROCLASSNAME');
    end;