从循环中的TreeView中删除用户选择的项时,如何避免无效索引错误?

sid*_*unk -1 delphi treeview listview vcl

我有一个树视图和一个列表视图,以及一个应该将所选项目从树视图移动到列表视图的按钮.选择和传输完全正常,但删除树视图中的项目不是.它仅在我在树视图下选择单个项目时才有效.当我有TreeView1.MultiSelect := True,然后有一个问题.

这是我正在使用的代码:

For i := 0 to TreeView1.Items.Count-1 do Begin
 If TreeView1.Items[i].Selected then
 Begin
 Itm := ListView1.Items.add;
 .....
 TreeView1.Items[i].Delete
Run Code Online (Sandbox Code Playgroud)

上述代码在某些选择后给出无效索引.不完美有时只添加两个中的一个.

尝试:

  1. For i := TreeView1.Items.Count to 1 do Begin
  2. 首先填充listview,然后尝试从treeview中删除,而不是同时执行它.同样的错误.
  3. 试图将Parent和Child存储在一个数组中,然后用名称删除它们.问题是未在树视图中选择的特定项目.

当我选择父节点中的所有元素被复制的最后一个元素时,这是不起作用的代码

for Itr := TreeView1.Items.Count-1 downto 0 do Begin
  if TreeView1.Items[Itr].Selected then
  begin
    Str := TreeView1.Items[Itr].Parent.Text + ' ,' + TreeView1.Items[Itr].Text;
    TrimLeft(Str);
    for k := 0 to SaveList.Count -1 do Begin
      If ansipos(Str, SaveList[k]) > 0 Then Begin
        Value := StringReplace(SaveList[k], Str, '',[rfReplaceAll, rfIgnoreCase]);
      End;
    End;
    Itm := ListView1.Items.Add;
    Itm.Caption := TreeView1.Items[Itr].Parent.Text;
    Itm.SubItems.Add(TreeView1.Items[Itr].Text);
    Itm.SubItems.Add(Value);
    TreeView1.Items[Itr].Delete
  end;
End;
Run Code Online (Sandbox Code Playgroud)

Tom*_*erg 5

将for循环更改为:

For i := TreeView1.Items.Count-1 downto 0 do 
....
Run Code Online (Sandbox Code Playgroud)

新代码出现后编辑

您没有显示实际的错误消息,也没有显示它发生在哪一行,但我认为它就在这一行上

Str := TreeView1.Items[Itr].Parent.Text + ' ,' + TreeView1.Items[Itr].Text;
Run Code Online (Sandbox Code Playgroud)

对于根级别的TreeView项目.那些没有父(IOW Item[itr].Parentnil),结果是Access violation错误.在尝试访问父项之前,您需要检查项目是否具有父项.

如果您的错误是其他原因,请澄清.


编辑,添加了解决方法

正如@MBo报道的那样,原因是选择在删除期间发生了变化.为防止这种情况,您可以使用以下解决方法.

例如,TreeView1_Deleting在表单中声明一个布尔字段,并OnChanging为树视图声明一个事件.

type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Button1: TButton;
    ...
    procedure TreeView1Changing(Sender: TObject; Node: TTreeNode;
      var AllowChange: Boolean);
  private
    TreeView1_Deleting: boolean;
  end;
Run Code Online (Sandbox Code Playgroud)

OnChanging事件的实施:

procedure TForm1.TreeView1Changing(Sender: TObject; Node: TTreeNode;
  var AllowChange: Boolean);
begin
  if TreeView1_Deleting then
    AllowChange := False;
end;
Run Code Online (Sandbox Code Playgroud)

最后,在删除所选节点的过程中

begin
  TreeView1_Deleting := True; // Add this line

  for i := TreeView1.Items.Count-1 downto 0 do
  begin
    if TreeView1.Items[i].Selected then
    begin
      // copy values to listview
      // and finally delete the node
      TreeView1.Items[i].Delete;
    end;
  end

  TreeView1_Deleting := False; // Add this line
end;
Run Code Online (Sandbox Code Playgroud)

还记得我之前说过的关于访问Parent根级节点属性的内容.

  • @siddharthtaunk请在您的问题中显示实际代码(复制 - 粘贴).从`count-1`循环到0不能给出无效索引. (2认同)