如何更新列表视图中的文本而不清除它

时间:2016-10-25 22:36:47

标签: c# .net winforms

我正在制作一个游戏,用于读取所有敌人信息(位置,健康等)并将其相应地存储在列表视图中。我目前正在使用这种方法:

        listView1.Items.Clear();
        string[] arr = new string[6];
        ListViewItem item;

        for (int i = 0; i < engine.maxPlayers; i++)
       {
           engine.enemy[i].readInfo(i);
        arr[0] = i.ToString()
        arr[1] = engine.enemy[i].name.ToString();
        arr[2] = engine.enemy[i].getRank(csgo.enemy[i].compRank);
        arr[3] = engine.enemy[i].Wins.ToString();
        arr[4] = engine.enemy[i].health.ToString();
        arr[5] = engine.enemy[i].armor.ToString();

        item = new ListViewItem(arr);
        listView2.Items.Add(item);
        }

这是每200毫秒完成一次以确保实时信息。 这在一定程度上起作用。它确实显示了一切正确。但是,它有两个很大的缺陷。 1:当它清除并重写数据时,它会不断闪烁。 2:如果我的列表视图只有10列,我需要读取20个玩家的数据,我无法向下滚动查看最后10个玩家,因为每次清除时,它会重置滚动条位置。

那么只能更新特定文本的文本吗?说我只想更新敌人[3]的健康状况,剩下的就剩下了。可以这样做吗?我不需要重新绘制胜利和排名等信息,因为它们在游戏过程中不会发生变化。

2 个答案:

答案 0 :(得分:0)

是的,您可以使用索引器直接引用您要更新的项目。例如:

listView2.Items[playerIndex] = new ListViewItem(arr);

至于相对于您的游戏引擎完成此操作,您将要使用协调设计模式,该模式涉及以下给定的游戏引擎列表(主)和列表视图(目标):

  1. 在Target中创建临时项目或键。叫这个ToDelete。
  2. 逐步掌握,添加任何不在Target中的条目,更新那些条目。从ToDelete中删除每个与Target匹配的内容。
  3. 从目标中删除ToDelete中剩余的所有项目。
  4. 更新:正如Slai所提到的,如果您不想替换整行,可以通过SubItems成员进行更新。

答案 1 :(得分:0)

我相信你必须首先用第一次调用的数据填充列表视图,然后每隔500ms-1000ms(我认为200ms什么都不提供),用新数据刷新列表视图。
类似的东西:

        private void InitialPopulation()
        {
            var listOfItems = new List<ListViewItem>();

            for (int i = 0; i < engine.maxPlayers; i++)
            {
                engine.enemy[i].readInfo(i);

                var item = new ListViewItem(i.ToString());
                item.Name = engine.enemy[i].name;
                item.SubItems.Add(engine.enemy[i].name);
                item.SubItems.Add(engine.enemy[i].getRank);
                item.SubItems.Add(engine.enemy[i].Wins);
                item.SubItems.Add(engine.enemy[i].health);
                item.SubItems.Add(engine.enemy[i].armor);

                listOfItems.Add(item);
            }

            listView1.BeginUpdate();
            listView1.Items.Clear();
            listView1.Items.AddRange(listOfItems.ToArray());
            listView1.EndUpdate();
        }

        private void RefreshData()
        {
            listView1.BeginUpdate();
            var listOfItems = new List<ListViewItem>();
            var playersNames = new List<string>();
            var itemsNames = new List<string>();


            for (int i = 0; i < engine.maxPlayers; i++)
            {
                engine.enemy[i].readInfo(i);

                playersNames.Add(engine.enemy[i].name);

                var items = listView1.Items.Find(engine.enemy[i].name, false);

                switch (items.Length)
                {
                    case 1: // update
                        items[0].SubItems[0].Text = engine.enemy[i].name;
                        items[0].SubItems[1].Text = engine.enemy[i].getRank;
                        items[0].SubItems[2].Text = engine.enemy[i].Wins;
                        items[0].SubItems[3].Text = engine.enemy[i].health;
                        items[0].SubItems[4].Text = engine.enemy[i].armor;
                        break;

                    case 0: // add
                        var item = new ListViewItem(i.ToString());
                        item.Name = engine.enemy[i].name;
                        item.SubItems.Add(engine.enemy[i].name);
                        item.SubItems.Add(engine.enemy[i].getRank);
                        item.SubItems.Add(engine.enemy[i].Wins);
                        item.SubItems.Add(engine.enemy[i].health);
                        item.SubItems.Add(engine.enemy[i].armor);
                        listOfItems.Add(item);
                        break;
                }
            }


            if (listOfItems.Count > 0)
                listView1.Items.AddRange(listOfItems.ToArray());

            foreach (ListViewItem item in listView1.Items)
                itemsNames.Add(item.Name);


            // check if there are more listview items than data.
            if (itemsNames.Count > playersNames.Count)
                foreach (var name in itemsNames.Except(playersNames))
                    listView1.Items.RemoveByKey(name);

            listView1.EndUpdate();
        }

我认为engine.enemy[i].name对每个palyer都是唯一的。

也许代码中有一些错误,因为我很长时间没有为winforms编写任何内容,但我认为你应该理解它。