0

I store in dictionary all the values of listView in dictionary-value and store its index in dictionary-keys at form load. I am using dictionary as a medium of index storage for corresponding transferred listitems.

Now i transfer from a to b on a button click (a listview is full and b is empty) then i do again transfer the same element from b to a on another button click. It is now appended at last when i do back to b->a transfer. But i want it to append on same index on which it was before transferring to a->b.

I mean when i do b->a transfer then it must go to same index where it used to stay before

My code is this (please correct me where i am wrong and please give me a solution)

        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;
        }     
test test
  • 141
  • 4
  • 15

2 Answers2

1

You can add a ListViewItemComparer to the list view. Like this.

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

And then in MoveSelectedItems:

this.listView1.ListViewItemSorter = new ListViewItemComparer();

Good luck.

Dick Bos
  • 384
  • 3
  • 8
  • Well, as you are keeping track of the index yourself, you can use that in the Compare to determine the placing in the Sorter. The Compare checks the index for each item in the listview and compares it with each other item. When it's larger the compare returns 1 (sort before) and smaller the compare returns -1 (sort after). – Dick Bos May 10 '16 at 11:20
  • Really worked? From what I see, it does nothing (keeps the items at the index where you insert them). – Ivan Stoev May 10 '16 at 11:30
  • It is temporary solution...still do not work if i continuously select some item from a and transfer to b , one by one (lets say in first attempt seventh item then first item and then third item. Now b contains third,first and seventh indexed item.) now i transfer seventh item from b->a (it crash, lets handle it in trycatch and add it at last of listview a) now add first. As a result third will be after fourth in the list. which is wrong answer. – test test May 10 '16 at 12:57
  • @IvanStoev Do you have any alternative ? – test test May 10 '16 at 12:57
  • @IvanStoev please see updated code in edited question – test test May 10 '16 at 13:00
1

What you actually need is, after taking the desired index from the dictionary, to search the items currently in the list view and find the actual insert position.

There are different way you can do that, here is one using binary search:

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);
    }
}

EDIT: Here is a [mcve] proving that it works:

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);
        }
    }
}
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • sorry it do not add anything in listview "a" (when i do a->b tranfer it works but when i tranfer back to a ..thne it do not add anyting in a) – test test May 10 '16 at 13:17
  • @please see my entire updated code, it still adds at last. – test test May 10 '16 at 13:23
  • Yep, I forgot to use `lvItem` instead of `temp`. I see you did it. Is it ok now? – Ivan Stoev May 10 '16 at 13:46
  • yaah.. i done that..but still when i do this..it put at last..but when i put the line this.listView1.ListViewItemSorter = new ListViewItemComparer(); after the line MoveSelectedItems(listView2, listView1, 1); in button2 click then it works perfectly. I dont know why ? – test test May 11 '16 at 03:37
  • It shouldn't put at last though. See the edited answer - I've added fully working example that works. If it doesn't work in your case, then you have something not shown. If you can provide sample similar to mine (what we call [mcve]) that presents the issue, I'll be glad to take a look at it. – Ivan Stoev May 11 '16 at 05:10