【问题标题】:How to transfer data from a to b Listview如何将数据从 a 传输到 b Listview
【发布时间】:2016-05-10 10:04:29
【问题描述】:

我将 listView 的所有值存储在字典值中,并在表单加载时将其索引存储在字典键中。 我正在使用字典作为相应传输列表项的索引存储介质。

现在我在单击按钮时从 a 转移到 b(列表视图已满,b 为空)然后我再次在单击另一个按钮时将相同的元素从 b 转移到 a。当我回到 b->a 转移时,它现在终于附加了。但我希望它附加到它在转移到 a->b 之前所在的同一索引上。

我的意思是当我做 b->a 转移时,它必须转到它以前停留的相同索引

我的代码是这样的(请纠正我的错误并给我一个解决方案)

        private void Form1_Load(object sender, EventArgs e)
        {
         //storing data in dictionary              
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MoveSelectedItems(listView1, listView2,0);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            MoveSelectedItems(listView2, listView1,1);
        }
        private  void MoveSelectedItems(ListView source, ListView target, int flag)
        {
                ListViewItem temp = source.SelectedItems[0];
                source.Items.Remove(temp);
                if(flag==0)//called when i do a->b
                {
                    target.Items.Add(temp);
                }
                else
                {
                    int index=getIndex(temp);
                    target.Items.Insert(index, temp);
                }
        }

        private  int getIndex(ListViewItem temp)
        {
            int index = 0;
            if (dictList.ContainsValue(temp.Text))
            {
                foreach (KeyValuePair<int, string> pair in dictList)
                    if (temp.Text.Equals(pair.Value))
                    {
                        index=Convert.ToInt32(pair.Key);
                        return index;
                    }             
            }    
            return index;
        }     

【问题讨论】:

  • 使用Dictionary 无法实现您想要的。有关更多信息,请参阅其他问题:stackoverflow.com/questions/7918328/…
  • @GuillaumeBeauvois 还有其他选择吗?
  • @GuillaumeBeauvois 请仔细阅读我想要达到的目标.. 我希望在列表视图中添加(不在字典中)
  • 我正在使用字典作为相应传输列表项的索引存储介质。

标签: c# .net winforms listview


【解决方案1】:

您真正需要的是,在从字典中获取 desired 索引后,搜索当前列表视图中的项目并找到实际插入位置。

有不同的方法可以做到这一点,这是一种使用二进制搜索的方法:

else
{
    foreach (ListViewItem item in source.SelectedItems)
    {
        ListViewItem lvItem = item.Clone() as ListViewItem;
        int index = dictList[item.Text];
        // Insert at appropriate position based on index value
        if (index == 0) // Always first
            target.Items.Insert(0, lvItem);
        else if (index == dictList.Count - 1) // Always last
            target.Items.Add(lvItem);
        else
        {
            // Binary search the current target items
            int lo = 0, hi = target.Items.Count - 1;
            while (lo <= hi)
            {
                int mid = lo + (hi - lo) / 2;
                if (index < dictList[target.Items[mid].Text])
                    hi = mid - 1;
                else
                    lo = mid + 1;
            }
            // Here lo variable contains the insert position
            target.Items.Insert(lo, lvItem);
        }
        source.Items.Remove(item);
    }
}

编辑:这是一个 [mcve] 证明它有效:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace Samples
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            var form = new Form();
            var splitView = new SplitContainer { Dock = DockStyle.Fill, Parent = form, Orientation = Orientation.Vertical };
            var listView1 = new ListView { Dock = DockStyle.Fill, Parent = splitView.Panel1, View = View.List };
            var listView2 = new ListView { Dock = DockStyle.Fill, Parent = splitView.Panel2, View = View.List };
            var buttonPanel = new Panel { Dock = DockStyle.Bottom, Parent = form };
            var button1 = new Button { Parent = buttonPanel, Left = 16, Top = 8, Text = ">" };
            var button2 = new Button { Parent = buttonPanel, Left = button1.Right + 16, Top = 8, Text = "<" };
            buttonPanel.Height = button1.Height + 16;

            var dictList = new Dictionary<string, int>
            {
                { "first", 0 },
                { "second", 1 },
                { "third", 2 },
                { "fourth", 3 },
                { "fifth", 4 },
                { "sixth", 5 },
                { "seventh", 6 },
            };
            foreach (var item in dictList)
                listView1.Items.Insert(item.Value, item.Key);

            Action<ListView, ListView, int> MoveSelectedItems = (ListView source, ListView target, int flag) =>
            {
                while (source.SelectedItems.Count > 0)
                {
                    var item = source.SelectedItems[0];
                    source.Items.Remove(item);
                    if (flag == 0)
                    {
                        target.Items.Add(item);
                    }
                    else
                    {
                        int index = dictList[item.Text];
                        // Insert at appropriate position based on index value
                        if (index == 0) // Always first
                            target.Items.Insert(0, item);
                        else if (index == dictList.Count - 1) // Always last
                            target.Items.Add(item);
                        else
                        {
                            // Binary search the current target items
                            int lo = 0, hi = target.Items.Count - 1;
                            while (lo <= hi)
                            {
                                int mid = lo + (hi - lo) / 2;
                                if (index < dictList[target.Items[mid].Text])
                                    hi = mid - 1;
                                else
                                    lo = mid + 1;
                            }
                            // Here lo variable contains the insert position
                            target.Items.Insert(lo, item);
                        }
                    }
                }
            };

            button1.Click += (sender, e) => MoveSelectedItems(listView1, listView2, 0);
            button2.Click += (sender, e) => MoveSelectedItems(listView2, listView1, 1);

            Application.Run(form);
        }
    }
}

【讨论】:

  • 抱歉,它没有在列表视图“a”中添加任何内容(当我执行 a->b 传输时它可以工作,但是当我传输回 a ..thne 时,它​​不会在 a 中添加任何内容)跨度>
  • @please 查看我的全部更新代码,最后还是添加了。
  • 是的,我忘记使用lvItem 而不是temp。我看你做到了。现在可以了吗?
  • 是啊..我做到了..但当我这样做时..它最后..但是当我放行时 this.listView1.ListViewItemSorter = new ListViewItemComparer();在 MoveSelectedItems(listView2, listView1, 1) 行之后;在button2点击然后它完美地工作。不知道为什么?
  • 它不应该放在最后。请参阅编辑后的答案 - 我添加了完全有效的示例。如果它在您的情况下不起作用,那么您有一些未显示的内容。如果您可以提供与我类似的示例(我们称之为minimal reproducible example),我会很乐意看看它。
【解决方案2】:

您可以将 ListViewItemComparer 添加到列表视图。像这样。

public class ListViewItemComparer : IComparer
{
    public int Compare(object x, object y)
    {
        return (((ListViewItem)x).Index > ((ListViewItem)y).Index ? 1 : -1);
    }
}

然后在 MoveSelectedItems 中:

this.listView1.ListViewItemSorter = new ListViewItemComparer();

祝你好运。

【讨论】:

  • 好吧,当您自己跟踪索引时,您可以在比较中使用它来确定排序器中的位置。 Compare 检查列表视图中每个项目的索引,并将其与其他项目进行比较。当它较大时,比较返回 1(排序前),较小时比较返回 -1(排序后)。
  • 真的有效吗?据我所知,它什么都不做(将项目保留在插入它们的索引处)。
  • 这是临时解决方案...如果我不断地从 a 中选择一些项目并一个接一个地转移到 b 仍然不起作用(假设第一次尝试第七项然后是第一项然后是第三项. 现在 b 包含第三个、第一个和第七个索引项。)现在我从 b->a 转移第七个项目(它崩溃,让我们在 trycatch 中处理它并在列表视图 a 的最后添加它)现在首先添加。结果,第三个将排在列表的第四个之后。这是错误的答案。
  • @IvanStoev 你有其他选择吗?
  • @IvanStoev 请查看已编辑问题中的更新代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多