微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

delphi – Treeview with checkboxes – 添加复选框行为

我正在使用复选框创建Treeview.我想出了如何切换到节点的复选框(过程ToggleTreeViewCheckBoxes).我添加了带有复选框位图的T ImageList组件,并在OnClick treeview事件中更改StateIndex.它工作正常,但我想添加其他行为.

我创建了treeview结构作为示例:

>根1

>父1(复选框)

>儿童1(复选框)
>儿童2(复选框)

>父2(复选框)

>儿童1(复选框)
>儿童2(复选框)

>根2

>父1(复选框)

>儿童1(复选框)
>儿童2(复选框)

>父2(复选框)

>儿童1(复选框)
>儿童2(复选框)

下面我附上你准备的示例代码,创建树视图并添加节点,复选框.

unit TreeViewCheckBoxes;

interface

uses
  Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,System.ImageList,Vcl.ImgList,Vcl.ComCtrls;

type
  TForm5 = class(TForm)
    ImageList1: timageList;
    TreeView1: TTreeView;
    procedure FormCreate(Sender: TObject);
    procedure TreeView1Click(Sender: TObject);
  private
    { Private declarations }
    procedure ToggleTreeViewCheckBoxes(Node:TTreeNode; cUnChecked,cChecked: Integer);
  public
    { Public declarations }
  end;

var
  Form5: TForm5;

const
  cStateUnCheck = 1;
  cStateChecked = 2;

   aRootList: Array[1..2] of String =
   (
      'Root 1','Root 2'
   );

implementation

{$R *.dfm}

{ TForm5 }

procedure TForm5.FormCreate(Sender: TObject);
var
   RootNode: TTreeNode;
   ParentNode: TTreeNode;
   ChildNode: TTreeNode;
   i: Integer;
begin
   for i := 1 to High(aRootList) do
   begin
      RootNode := TreeView1.Items.Add(nil,aRootList[i]);

      ParentNode := TreeView1.Items.AddChild(RootNode,'Parent 1');
      ParentNode.StateIndex := 1;
      ChildNode := TreeView1.Items.AddChild(ParentNode,'Child 1');
      ChildNode.StateIndex := 1;
      ChildNode := TreeView1.Items.AddChild(ParentNode,'Child 2');
      ChildNode.StateIndex := 1;    

      ParentNode := TreeView1.Items.AddChild(RootNode,'Parent 2');
      ParentNode.StateIndex := 1;
      ChildNode := TreeView1.Items.AddChild(ParentNode,'Child 2');
      ChildNode.StateIndex := 1;
   end;
end;

procedure TForm5.ToggleTreeViewCheckBoxes(Node: TTreeNode; cUnChecked,cChecked: Integer);
begin
   if Assigned(Node) then
   begin
      if Node.StateIndex = cUnChecked then
         Node.StateIndex := cChecked
      else if Node.StateIndex = cChecked then
         Node.StateIndex := cUnChecked;
   end;
end;

procedure TForm5.TreeView1Click(Sender: TObject);
var
   P: TPoint;
begin
   GetCursorPos(P);
   P := TreeView1.ScreenToClient(P);
   if (htOnStateIcon in TreeView1.GetHitTestInfoAt(P.X,P.Y)) then
      ToggleTreeViewCheckBoxes(TreeView1.Selected,cStateUnCheck,cStateChecked);
end;    
end.

问题:

1)我该怎么做呢:如果我点击任何Parent复选框节点,所有子节点都是未选中的?

2)您是否知道为所有子节点动态添加节点和设置StateIndex的更好方法?我的意思是没有每次都使用行ChildNode.StateIndex:= 1;

解决方法

1) How can I do something like that: If I click on any Parent checkBox node,all child nodes are unchecked?

您必须手动遍历所有子项,例如:

procedure TForm5.SetTreeViewCheckState(Node: TTreeNode; StateIndex: Integer; Recursive: Boolean);
begin
  Node.StateIndex := StateIndex;
  if not Recursive then Exit;
  for I := 0 to Node.Count-1 do
    SetTreeViewCheckState(Node.Item[I],StateIndex,True);
end;

procedure TForm5.ToggleTreeViewCheckBoxes(Node: TTreeNode);
var
  I: Integer;
begin
  if Assigned(Node) then
  begin
    if Node.StateIndex = cStateUnCheck then
      SetTreeViewCheckState(Node,cStateChecked,False);
    else if Node.StateIndex = cStateChecked then
      SetTreeViewCheckState(Node,True);
  end;
end;

2) Do you kNow any better way to dynamically add nodes and set StateIndex for all childs? I mean no every time use line ChildNode.StateIndex := 1;

对不起,但这是唯一的方法.但是你可以将它包装在一个函数中:

procedure TForm5.FormCreate(Sender: TObject);
var
  RootNode: TTreeNode;
  ParentNode: TTreeNode;
  i: Integer;
begin
  for i := Low(aRootList) to High(aRootList) do
  begin
    RootNode := TreeView1.Items.Add(nil,aRootList[i]);

    ParentNode := AddChildNodeWithState(RootNode,'Parent 1');
    AddChildNodeWithState(ParentNode,'Child 1');
    AddChildNodeWithState(ParentNode,'Child 2');

    ParentNode := AddChildNodeWithState(RootNode,'Parent 2');
    AddChildNodeWithState(ParentNode,'Child 2');
  end;
end;

function TForm5.AddChildNodeWithState(AParentNode: TTreeNode,const ACaption: String; AStateIndex: Integer = 1): TTreeNode;
begin
  Result := TreeView1.Items.AddChild(AParentNode,ACaption);
  Result.StateIndex := AStateIndex;
end;

或者,您可以创建一个class helper(也可以用于切换逻辑):

type
  TTreeNodeHelper = class helper for TTreeNode
  public
    function AddChildWithState(const ACaption: string; AStateIndex: Integer = 1): TTreeNode;
    procedure SetCheckState(StateIndex: Integer; Recursive: Boolean);
    procedure ToggleCheckState;
  end;

function TTreeNodeHelper.AddChildWithState(const ACaption: string; AStateIndex: Integer = 1): TTreeNode;
begin
  Result := Self.TreeView.Items.AddChild(Self,ACaption);
  Result.StateIndex := AStateIndex;
end;

procedure TTreeNodeHelper.SetCheckState(StateIndex: Integer; Recursive: Boolean);
begin
  Self.StateIndex := StateIndex;
  if not Recursive then Exit;
  for I := 0 to Self.Count-1 do
    Self.Item[I].SetCheckState(StateIndex,True);
end;

procedure TTreeNodeHelper.ToggleCheckState;
var
  I: Integer;
begin
  if Self.StateIndex = cStateUnCheck then
    SetCheckState(cStateChecked,False);
  else if Self.StateIndex = cStateChecked then
    SetCheckState(cStateUnCheck,True);
  end;
end;
procedure TForm5.FormCreate(Sender: TObject);
var
  RootNode: TTreeNode;
  ParentNode: TTreeNode;
  i: Integer;
begin
  for i := Low(aRootList) to High(aRootList) do
  begin
    RootNode := TreeView1.Items.Add(nil,aRootList[i]);

    ParentNode := RootNode.AddChildWithState('Parent 1');
    ParentNode.AddChildWithState('Child 1');
    ParentNode.AddChildWithState('Child 2');

    ParentNode := RootNode.AddChildWithState('Parent 2');
    ParentNode.AddChildWithState('Child 1');
    ParentNode.AddChildWithState('Child 2');
  end;
end;

procedure TForm5.TreeView1Click(Sender: TObject);
var
  P: TPoint;
begin
  GetCursorPos(P);
  P := TreeView1.ScreenToClient(P);
  if (htOnStateIcon in TreeView1.GetHitTestInfoAt(P.X,P.Y)) then
    TreeView1.GetNodeAt(P.X,P.Y).ToggleCheckState;
end;

如果您使用的是不支持类助手的旧版Delphi,则可以从TTreeNode派生一个类,并将其与TreeView的OnCreateNodeClass事件一起使用,例如:

type
  TMyTreeNode = class(TTreeNode)
  public
    function AddChildWithState(const ACaption: string; AStateIndex: Integer = 1): TTreeNode;
    procedure SetCheckState(StateIndex: Integer; Recursive: Boolean);
    procedure ToggleCheckState;
  end;

function TMyTreeNode.AddChildWithState(const ACaption: string; AStateIndex: Integer = 1): TTreeNode;
begin
  Result := Self.TreeView.Items.AddChild(Self,ACaption);
  Result.StateIndex := AStateIndex;
end;

procedure TMyTreeNode.SetCheckState(StateIndex: Integer; Recursive: Boolean);
begin
  Self.StateIndex := StateIndex;
  if not Recursive then Exit;
  for I := 0 to Self.Count-1 do
    TMyTreeNode(Self.Item[I]).SetCheckState(StateIndex,True);
end;

procedure TMyTreeNode.ToggleCheckBoxes;
var
  I: Integer;
begin
  if Self.StateIndex = cStateUnCheck then
    SetCheckBoxes(cStateChecked,cStateUnChecked);
  else if Self.StateIndex = cStateChecked then
    SetCheckBoxes(cStateUnCheck,cStateUnChecked);
  end;
end;
procedure TForm5.FormCreate(Sender: TObject);
var
  RootNode: TTreeNode;
  ParentNode: TTreeNode;
  i: Integer;
begin
  for i := Low(aRootList) to High(aRootList) do
  begin
    RootNode := TreeView1.Items.Add(nil,aRootList[i]);

    ParentNode := TMyTreeNode(RootNode).AddChildWithState('Parent 1');
    TMyTreeNode(ParentNode).AddChildWithState('Child 1');
    TMyTreeNode(ParentNode).AddChildWithState('Child 2');

    ParentNode := TMyTreeNode(RootNode).AddChildWithState('Parent 2');
    TMyTreeNode(ParentNode).AddChildWithState('Child 1');
    TMyTreeNode(ParentNode).AddChildWithState('Child 2');
  end;
end;

procedure TForm5.TreeView1Click(Sender: TObject);
var
  P: TPoint;
begin
  GetCursorPos(P);
  P := TreeView1.ScreenToClient(P);
  if (htOnStateIcon in TreeView1.GetHitTestInfoAt(P.X,P.Y)) then
    TMyTreeNode(TreeView1.GetNodeAt(P.X,P.Y)).ToggleCheckState;
end;    

procedure TForm5.TreeView1CreateNodeClass(Sender: TCustomTreeView; var NodeClass: TTreeNodeClass)
begin
  NodeClass := TMyTreeNode;
end;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐