0

I have a class called Picture and that has a name and size (int) property.

I was going to sort them using size, but not the displayed file name which is the item name in the listview.

I implemented IComparer<Picture> for the Picture type, and then when I write this:

this.PicList.ListViewItemSorter = AllPictures[0];

or

this.PicList.ListViewItemSorter = Picture;

they don't compile.

How do I do this? On MSDN it shows a separate class for the sorter but can I do it built-in with the used type Picture?

3
  • Picture is a type? You need to give it an instance of Picture, not the type. What's the error? Commented Jul 15, 2009 at 0:29
  • Yes, it's a struct. The error is can't convert Picture to IComparer. In #1, I am passing an instance of the picture that doesn't work. Commented Jul 15, 2009 at 0:31
  • Why someone downvoted it? It's a valid question. Commented Jul 15, 2009 at 9:15

3 Answers 3

1

you need to give it an actual instance of your Picture class, not the type. Also, your ListViewItemSorter will actually call the Comparer by passing it the ListViewItem not the Picture class, you can add an instance of the Picture class to the Tag property of your ListViewItem.

Something like this, this is a very rough implementation, just to give you an idea. You can implement your own error handling.

Picture test1 = new Picture() { Name = "Picture #1", Size = 54 };
Picture test2 = new Picture() { Name = "Picture #2", Size = 10 };

this.listView1.ListViewItemSorter = test1;

this.listView1.Items.Add(new ListViewItem(test1.Name) { Tag = test1 });
this.listView1.Items.Add(new ListViewItem(test2.Name) { Tag = test2 });

 public class Picture : IComparer
    {
        public string Name { get; set; }
        public int Size { get; set; }

        #region IComparer Members

        public int Compare(object x, object y)
        {
            Picture itemA = ((ListViewItem)x).Tag as Picture;
            Picture itemB = ((ListViewItem)y).Tag as Picture;

            if (itemA.Size < itemB.Size)
                return -1;

            if (itemA.Size > itemB.Size)
                return 1;

            if (itemA.Size == itemB.Size)
                return 0;

            return 0;

        }

The output is:

  • Picture #2
  • Picture #1

Here is an MSDN Link

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. This is what I needed. This made me realize that the sorting shouldn't be part of the Picture type. I thought it uses the Picture type, not the ListViewItem. Now it's clear.
1

Another implementation you can try is to associate each ListViewItem index with your custom class/struct instance stored in a Dictionary<int, Picture> instance. Your custom list view sorter class could be written with that in mind like so:

public partial class Form1 : Form
{
    public Form1()
    {
        ...

        ListView lv = new ListView();
        lv.ListViewItemSorter = new MyCustomSorter(this);
    }

    private Dictionary<int, Picture> _pictures = new Dictionary<int,Picture>();

    private class MyCustomSorter : IComparer
    {
        private Form1 _parent;

        internal MyCustomSorter(Form1 form)
        {
            _parent = form;
        }

        #region IComparer Members

        public int Compare(object x, object y)
        {
            ListViewItem item1 = x as ListViewItem;
            ListViewItem item2 = y as ListViewItem;

            if (x != null)
            {
                if (y != null)
                {
                    Picture p1 = _parent._pictures[item1.Index];
                    Picture p2 = _parent._pictures[item2.Index];

                    return string.Compare(p1.Location, p2.Location);
                }

                // X is deemed "greater than" y
                return 1;
            }
            else if (y != null)
                return -1;      // x is "less than" y

            return 0;
        }

        #endregion
    }
}

public class Picture
{
    private string _location;

    public string Location{
        get { return _location; }
    }
}

Comments

1

Stan's solution will work, but, on behalf of your users, I'd strongly suggest you don't hard code the sorting order. On a ListView, everyone expects to be able to sort by clicking on the header.

ObjectListView (an open source wrapper around .NET WinForms ListView) provides sort-on-click functionality for free. It could even show a thumbnail of your pictures in its own column if you want it to.

1 Comment

Yes. I completely agree. I just showed him an implementation and why his was not working. But I agree it should be done on a column header.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.