TTreeView完整的枚举和递归算法

TTreeView完整的枚举和递归算法

一、TTreeView

(一)、重要属性

Memo_Test.Lines.Add(

      ‘TTreeView重要属性:’

    +',1、可见数:'+IntToStr((LAddObject as TTreeViewItem).VisibleCount)        //:该节点所有展开的下级总数
    +',2、Item个数:'+IntToStr((LAddObject as TTreeViewItem).Count)                //:该节点所有下级总数>=0,末级Count=0
    +',3、几级:'+IntToStr((LAddObject as TTreeViewItem).Level)                       //:该节点的级数:级数>=1 
    +',4、全局索引:'+IntToStr((LAddObject as TTreeViewItem).GlobalIndex)     //:该节点所有展开的下级的重新的自动索引(作用不大)

);

5、该节点的父节点:

     (LAddObject as TTreeViewItem).ParentItem

6、该节点被勾选IsChecked:

     if (LAddObject as TTreeViewItem).IsChecked=True then ;

7、该节点是否展开其下级、展开或收拢其下级:

  if FTreeViewItemCurrt.IsExpanded=false then
    FTreeViewItemCurrt.IsExpanded:=true
  else FTreeViewItemCurrt.IsExpanded:=false;

8、TreeView展开或收拢所有下级:

  FIFCollapse:=not FIFCollapse;
  if FIFCollapse=false then
    TreeView.CollapseAll       //收拢
  else TreeView.ExpandAll;  //展开

9、TreeView改变了勾选状态:

  procedure TreeViewChangeCheck(Sender: TObject);

  begin

     if (LAddObject as TTreeViewItem).IsChecked=True then ;  //:该节点改变了勾选状态

     if (LAddObject as TTreeViewItem).ParentItem.IsChecked=True then ;  //:该节点的父节点改变了勾选状态

  end;

10、TreeView的某节点被点击:

  LTreeViewItem.OnClick:=LAddObjectOnClick;  //:定义某节点的点击事件:LAddObjectOnClick:写代码

11、TreeView的动态增加节点:

  LTreeViewItem:=TTreeViewItem.Create( AOwnerObject );  //:所有者:应为窗体或TFrame
  LTreeViewItem.Index:=AIndex;      //:11.1、索引会被TTreeView的节点自动索引所覆盖:应使用自定义索引LTreeViewItem.Tag
  LTreeViewItem.Name:=AName;    //:11.2、节点命名:不能重复
  LTreeViewItem.Text:=AText;          //:11.3、节点的显示文本
  LTreeViewItem.Parent:=AParent;  //:11.4、父组件:关键:父组件可以是TreeView,也可以是某个TreeViewItem节点
      //LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AParent.Name;
  LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AText;    //:11.5、节点的个性化标签文字
  LTreeViewItem.ImageIndex:=ImageIndex;                                 //:11.6、节点的个性化图片索引

  LTreeViewItem.Tag:=AIndex;          //:11.7、自定义索引LTreeViewItem.Tag
  SetLength(FTreeViewItemCheckedCount,LTreeViewItem.Tag+1);  //:11.8:TreeViewItem被勾中的数组长度
  FTreeViewItemCheckedCount[LTreeViewItem.Tag]:=0;         //:初始化TreeViewItem被勾中的数组
       //:初始化TreeViewItem被勾中的数组TreeView.OnChangeCheck


    ///<summary>动态新增TreeView的TreeViewItem节点:</summary>

function TForm2.CreateATreeViewItems(
const AIndex:Integer;
      AName:string;
      AText:string;
      ATreeFiledName:string;
      AParent:TFmxObject;
      //:非常关键的参数:指明该节点:
        //:其父节点是TTreeView还是它的上级递归TTreeViewItem
      ImageIndex:Integer;
      ASizeHeight,ASizeWidth:Single;
      MarginsLeft:Single;
      AOwnerObject:TFmxObject
  ):TTreeViewItem;
var LTreeViewItem:TTreeViewItem;
begin
  InitATreeViewItems(TreeView_WorkSpace_Menus,FIFInited);

  LTreeViewItem:=TTreeViewItem.Create( AOwnerObject ); //:所有者:应为窗体或TFrame
  LTreeViewItem.Index:=AIndex;//:索引会被TTreeView的节点自动索引所覆盖:应使用自定义索引LTreeViewItem.Tag
  LTreeViewItem.Name:=AName;  //:节点命名:不能重复
  LTreeViewItem.Text:=AText;  //:节点的显示文本
  LTreeViewItem.Parent:=AParent;//:父组件:关键:父组件可以是TreeView,也可以是某个TreeViewItem节点
  //LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AParent.Name;
  LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AText;  //:节点的个性化标签文字
  LTreeViewItem.ImageIndex:=ImageIndex;   //:节点的个性化图片索引

  LTreeViewItem.Tag:=AIndex;  //:自定义索引LTreeViewItem.Tag
  SetLength(FTreeViewItemCheckedCount,LTreeViewItem.Tag+1);
  FTreeViewItemCheckedCount[LTreeViewItem.Tag]:=0;
    //:初始化TreeViewItem勾中数组TreeView.OnChangeCheck
  LTreeViewItem.Align:=TAlignLayout.Left;
  LTreeViewItem.IsChecked:=false;
  LTreeViewItem.IsExpanded:=false;
  LTreeViewItem.IsSelected:=false;
  LTreeViewItem.StyleLookup:='treeviewitemstyle';
  LTreeViewItem.StyledSettings:=
    LTreeViewItem.StyledSettings-
    [TStyledSetting.Family,
     TStyledSetting.Size,
     TStyledSetting.FontColor,
     TStyledSetting.Other
    ];
  LTreeViewItem.TextSettings.FontColor
    :=TAlphaColor($FF1373A9);
  LTreeViewItem.TextSettings.Font.Family:='微软雅黑';
  LTreeViewItem.TextSettings.Font.Size:=16;
  LTreeViewItem.Size.Height:=ASizeHeight;
  LTreeViewItem.Size.Width:=ASizeWidth;
  LTreeViewItem.Margins.Left:=MarginsLeft;
  LTreeViewItem.Position.Y:=AIndex*40;

  LTreeViewItem.IsExpanded:=false;
  LTreeViewItem.OnClick:=LAddObjectOnClick;

  Result:=LTreeViewItem;
end;

(二)、关键处理好

12、if   (LAddObject as TTreeViewItem).Level=1  then ;   //:处理好顶级

13、if  ( (LAddObject as TTreeViewItem).Level=1) and ((LAddObject as TTreeViewItem).Count>0)  then ;   //:处理好顶级但非末级的节点

14、if  ( (LAddObject as TTreeViewItem).Level=1) and ((LAddObject as TTreeViewItem).Count=0)  then ;   //:处理好顶级且为末级的节点

15、if  ( (LAddObject as TTreeViewItem).Level>1) and ((LAddObject as TTreeViewItem).Count>0)  then ;   //:处理好中间级的节点

16、if  ( (LAddObject as TTreeViewItem).Level>1) and ((LAddObject as TTreeViewItem).Count=0)  then ;   //:处理好非顶级且为末级的节点

二、TTreeView枚举其下被勾选的节点

procedure TForm2.ControlAction_btnEnumCheckedExecute(Sender: TObject);
begin
//遍历TreeView选中的节点:
  FTreeViewSelectAllOrNot:=false;
  EnumChecked(false,FTreeViewSelectAllOrNot);
end;


function TForm2.EnumChecked(
  const AIFAncester:Boolean=true;
        AIFUpdateCheckedStatus:Boolean=true):TStringList;
var LAddObject:TFmxObject;
    LStringList:TStringList;
    LCircle:Integer;
    LSeparator: array of char;
    LLineOfStringList :TArray<string>;
begin
//枚举TreeView选中的节点并决定是否变更选中状态:
  LStringList:=TStringList.Create;
  LTreeViewItemCount:=0;
  try
    TreeView_WorkSpace_Menus.EnumControls(
      procedure (const AControl: TControl; var Done: boolean)
      begin
        if (AControl.ClassName = 'TTreeViewItem') then
        begin
          LAddObject:=TTreeViewItem(AControl);
          if (AIFUpdateCheckedStatus=true) then
          begin
            if (LAddObject as TTreeViewItem).IsChecked=True then
              (LAddObject as TTreeViewItem).IsChecked:=false
            else (LAddObject as TTreeViewItem).IsChecked:=True;
          end;
          if (LAddObject as TTreeViewItem).IsChecked=True then
          begin
            if (AIFAncester=true) then
            begin
              if (LAddObject.TagString).Substring(
                   (LAddObject.TagString).IndexOf('=')+1
                  ,length(LAddObject.TagString) )=(LAddObject as TTreeViewItem).Text
              then
                LStringList.Add(LAddObject.TagString);
                //:格式:LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AParent.Name;
            end else
            if (AIFAncester=false) then
            begin
              if ( (LAddObject as TTreeViewItem).Count=0 )
              then //:找到末级反推上级
              begin
                if (LAddObject as TTreeViewItem).Level>1 then
                begin
                  if ((LAddObject as TTreeViewItem).ParentItem.Count
                    =FTreeViewItemCheckedCount[(LAddObject as TTreeViewItem).ParentItem.Tag]) then
                  begin //:找到了上级打勾:即下级全打勾
                    if LStringList.Text.Contains((LAddObject as TTreeViewItem).ParentItem.TagString)
                      =false then
                    begin
                      //Memo_Test.Lines.Add('找到了上级打勾');
                      LStringList.Add((LAddObject as TTreeViewItem).ParentItem.TagString);
                    end;
                    Done:=false;
                  end else
                  begin //:else:找到了只有个别下级打勾
                    if LStringList.Text.Contains((LAddObject as TTreeViewItem).TagString)
                      =false then
                    begin
                      //Memo_Test.Lines.Add('找到了只有个别下级打勾');
                      LStringList.Add((LAddObject as TTreeViewItem).TagString);
                    end;
                    Done:=false;
                  end;
                end;
                if (LAddObject as TTreeViewItem).Level=1 then
                begin //:末级是顶级
                  if LStringList.Text.Contains((LAddObject as TTreeViewItem).TagString)
                    =false then
                  begin
                    //Memo_Test.Lines.Add('找到了末级是顶级的节点');
                    LStringList.Add((LAddObject as TTreeViewItem).TagString);
                  end;
                  Done:=false;
                end;
              end;
              //:格式:LTreeViewItem.TagString:=ATreeFiledName.Trim+'='+AText;
            end;
          end;
        end;
        Done:=false;//:不要停继续找下一个
      end
      ,true //:只枚举可见的组件
    );
    //LStringList.Sort; //:枚举类型只能按照索引号index排序
    //LStringList的调用方法如下(可传递给sql条件拼接):测试枚举结果:
    //{
    //Memo_Test.Lines.Clear;
    Memo_Test.BringToFront; Memo_Test.Visible:=true;
    Memo_Test.Position.X:=361;
    Memo_Test.BeginUpdate;
    SetLength(LSeparator,1);
    LSeparator[0]:='=';
    for LCircle := 0 to LStringList.Count-1 do
    begin
      SetLength(LLineOfStringList,length(LStringList[LCircle]));
      LLineOfStringList[0]:=LStringList[LCircle].Split(LSeparator[0])[0];
      LLineOfStringList[1]:=LStringList[LCircle].Split(LSeparator[0])[1];
      Memo_Test.Lines.Add(LLineOfStringList[0]+'='+LLineOfStringList[1]);
      //Memo_Test.Lines.Add(LStringList[LCircle]);
    end;
    Memo_Test.EndUpdate; //}
    Result:=LStringList;
  finally
    FreeAndNil(LStringList);
  end;

end;

三、TTreeView与枚举和递归算法:TTreeView枚举并递归加载外部数据源

    ///<summary>某节点TTreeViewItem被勾中或取消勾中处理其节点及其上下级节点:</summary>


procedure TForm2.TreeView_WorkSpace_MenusChangeCheck(Sender: TObject);
var LLevel:Integer;

  procedure LEnumControls(LFmxObject:TFmxObject;EnumControlClassName:string);
  begin
    //1、处理ChangeCheck的上级:
    if (LFmxObject as TTreeViewItem).IsChecked=true then
    begin
      if (LLevel>1) then//:基线条件
      begin
        try
          if FTreeViewItemCheckedCount[FTreeViewItemTag]
            < (LFmxObject as TTreeViewItem).ParentItem.Count then
          begin
            if LErgodicParent<>'父已枚举' then
              INC(FTreeViewItemCheckedCount[FTreeViewItemTag]);
            //:上级+1
            LErgodicParent:='';
            Memo_Test.Lines.Add('枚举对象:'+(Sender as TTreeViewItem).Text+':上级:'+(Sender as TTreeViewItem).ParentItem.Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
          end;
        finally
          if FTreeViewItemCheckedCount[FTreeViewItemTag]
            = (Sender as TTreeViewItem).ParentItem.Count then
          begin
            LErgodicParent:='父已枚举';
            if (Sender as TTreeViewItem).ParentItem.IsChecked=false then
              (Sender as TTreeViewItem).ParentItem.IsChecked:=true;
            //:开始递归:上级枚举
          end;
        end;
      end else
      if (LLevel=1) then//:基线条件
      begin
        if FTreeViewItemCheckedCount[FTreeViewItemTag]
          < (LFmxObject as TTreeViewItem).Count then
        begin
          if LErgodicParent<>'父已枚举' then
            INC(FTreeViewItemCheckedCount[FTreeViewItemTag]);
          //:上级+1
          LErgodicParent:='';
          Memo_Test.Lines.Add('枚举对象:'+(Sender as TTreeViewItem).Text+':上级:'+(Sender as TTreeViewItem).Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
        end;
      end;
    end else
    if (LFmxObject as TTreeViewItem).IsChecked=false then
    begin
      if (LLevel>1) then//:基线条件
      begin
        try
          if FTreeViewItemCheckedCount[FTreeViewItemTag]
            >0 then
          begin
            if LErgodicParent<>'父已枚举' then
              DEC(FTreeViewItemCheckedCount[FTreeViewItemTag]);
            //:上级-1
            LErgodicParent:='';
            Memo_Test.Lines.Add('枚举对象:'+(Sender as TTreeViewItem).Text+':上级:'+(Sender as TTreeViewItem).ParentItem.Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
          end;
        finally
          if FTreeViewItemCheckedCount[FTreeViewItemTag]
            = 0 then
          begin
            LErgodicParent:='父已枚举';
            if (Sender as TTreeViewItem).ParentItem.IsChecked=true then
              (Sender as TTreeViewItem).ParentItem.IsChecked:=false;
            //:开始递归:上级枚举
          end;
        end;
      end else
      if (LLevel=1) then//:基线条件
      begin
        if FTreeViewItemCheckedCount[FTreeViewItemTag]
          >0 then
        begin
          if LErgodicParent<>'父已枚举' then
            DEC(FTreeViewItemCheckedCount[FTreeViewItemTag]);
          //:上级-1
          LErgodicParent:='';
          Memo_Test.Lines.Add('枚举对象:'+(Sender as TTreeViewItem).Text+':上级:'+(Sender as TTreeViewItem).Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
        end;
      end;
    end;
    //2、处理ChangeCheck的本级枚举:
    try
      LErgodicParent:='';
      LFmxObject.EnumObjects(//const Proc: TFunc<TFmxObject, TEnumProcResult>
        function (LControl:TFmxObject):TEnumProcResult
          var LEnumProcResult:TEnumProcResult;
        begin
          //2.1、处理ChangeCheck的本级枚举到其下级:
          if LControl.ClassName=EnumControlClassName then
          begin
            if EnumControlClassName='TTreeViewItem' then
            begin
              if (LFmxObject as TTreeViewItem).IsChecked=true then
              begin
                //Memo_Test.Lines.Add('枚举到了下级');
                if (LControl as TTreeViewItem).IsChecked=false then
                begin
                  (LControl as TTreeViewItem).IsChecked:=true;
                end;
                  //:开始递归:(本级有下级)中间级枚举
              end;
              if (LFmxObject as TTreeViewItem).IsChecked=false then
              begin
                if (LControl as TTreeViewItem).IsChecked=true then
                begin
                  (LControl as TTreeViewItem).IsChecked:=false;
                end;
                  //:开始递归:(本级有下级)中间级枚举
              end;
            end;
          end;
          //2.1、处理ChangeCheck的本级枚举为末级:
          if LControl.ClassName<>EnumControlClassName then
          begin
            //Memo_Test.Lines.Add('末级被勾中:没有枚举到下级');
            //Memo_Test.Lines.Add('枚举对象:'+(LFmxObject as TTreeViewItem).Text+':上级:'+(LFmxObject as TTreeViewItem).ParentItem.Text+':被勾中数:'+IntToStr(FTreeViewItemCheckedCount[FTreeViewItemTag]) );
          end;
          Result:=TEnumProcResult.Continue;//:直到再无可枚举的下级

        end
      );
    finally
    end;

  end;
begin
  if FIFInited=false then exit//:必须先完成初始化: 初始化在Checked:=false
  else
  begin
    LLevel:=(Sender as TTreeViewItem).Level;
    if (LLevel=1) then
    begin
      FTreeViewItemTag:=(Sender as TTreeViewItem).Tag;
      //1、枚举子节点及其下级节点,自动勾或去勾:
      //:同时子节点会开始递归本单元:
      LEnumControls((Sender as TTreeViewItem),'TTreeViewItem');
    end else
    if (LLevel>1) then
    begin
      FTreeViewItemTag:=(Sender as TTreeViewItem).ParentItem.Tag;
      //1、枚举子节点及其下级节点,自动勾或去勾:
      //:同时子节点会开始递归本单元:
      LEnumControls((Sender as TTreeViewItem),'TTreeViewItem');
    end;

  end;
end;

四、TreeView父Item和子Item勾选互动:

  TTreeView = class(TCustomTreeView)
  published
       property OnChangeCheck;  //.....(还有很多发布属性)
           //:该属性的父类为受保护属性:  protected TCustomTreeView.OnChangeCheck
   end;

  TMyTreeView =Class(TTreeView)
  private
  protected
  public
  published
       // 我要改写并将其发布出来供调用者和RttiType使用:
       procedure OnChangeCheck( AItem :TObject );//:protected TCustomTreeView.OnChangeCheck
  end;
  // 实现代码如下:

implementation

{$R *.fmx}
{TMyTreeView}
procedure TMyTreeView.OnChangeCheck( AItem :TObject );
var LLoop,
    LCountAllCheckedOfAParentItem,
    LCountAllUnCheckedOfAParentItem :Integer;
    LItem,
    LParentItem: TTreeViewItem;
begin
  inherited DoChangeCheck( AItem as TTreeViewItem );
      {
      procedure TCustomTreeView.DoChangeCheck( const Item: TTreeViewItem );
      begin
        if Assigned(FOnChangeCheck) then
          FOnChangeCheck(Item);
      end;
      }  

  LItem := TTreeViewItem(AItem as TTreeViewItem);
  for LLoop:=0 to LItem.Count - 1 do
     LItem.Items[LLoop].IsChecked := LItem.IsChecked;
  if TTreeViewItem(LItem).ParentItem<>nil then
  begin
    LParentItem :=TTreeViewItem(LItem).ParentItem;
    LCountAllCheckedOfAParentItem:=0;
    for LLoop:=0 to LParentItem.Count - 1 do
      if LParentItem.Items[LLoop].IsChecked=true then
        LCountAllCheckedOfAParentItem
          :=LCountAllCheckedOfAParentItem+1;
    if LCountAllCheckedOfAParentItem=LParentItem.Count then
    begin
      LParentItem.IsChecked:=true;
    end;
    LCountAllUnCheckedOfAParentItem:=LParentItem.Count;
    for LLoop:=0 to LParentItem.Count - 1 do
      if LParentItem.Items[LLoop].IsChecked=false then
        LCountAllUnCheckedOfAParentItem
          :=LCountAllUnCheckedOfAParentItem-1;
    if LCountAllUnCheckedOfAParentItem=0 then
    begin
      LParentItem.IsChecked:=false;
    end;
  end;
end;

//  调用代码:
procedure TForm2.FormCreate(Sender: TObject);
var LTreeView :TMyTreeView;
begin
    LTreeView :=TMyTreeView.Create(TreeView1);  // :TreeView1 :UI中的TreeView组件
    TreeView1.OnChangeCheck :=LTreeView.OnChangeCheck;
end; 

五、TTreeView枚举与递归效果

发布了61 篇原创文章 · 获赞 6 · 访问量 5559

猜你喜欢

转载自blog.csdn.net/pulledup/article/details/103687816
今日推荐