Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to select the 1st item (the one at the top) of an ordered ListView

Status
Not open for further replies.

polocar

Programmer
Sep 20, 2004
89
IT
Hi,
I’m using Visual C# 2005 (part of Visual Studio 2005 Professional Edition), and I have the following problem:
I populate a ListView object with several items, and at the end of this process I put a statement that orders the ListView by a certain column and in a certain order (ascending or descending, it doesn’t matter). To do that, I have defined a derived class of the IComparer class (as explained in the Visual Studio MSDN Library).
Now I would like to select the first item of the list (the one at the top, in the first position), but if I write the statement

ListViewItem1.Items[0].Selected = true;

the first item of the NOT ordered list is selected (so, probably not the item at the top, but an item in the middle of the list).
I have also tried to force the ListView ordering as first thing, and then populate the list, but unfortunately the result is the same…

Do you know if there is a way to do that (a particular method or property of the ListView class, a prestige game, or so on)?

Thank you very much
 
Did you try this?

listView1.TopItem.Selected = true;

It assumes the view is scrolled to the top when you call it but I assume this is the case in your scenario.
 
Hi Aptitude,
I tried your suggestion (it seemed perfect for my case), but unfortunately it doesn't function...
If you have time to spend, I have prepared two files with the code samples.
The project creates a ListView object with 2 columns, the first one (column 0) with numbers from 1 to 10, the second one (column 1) with numbers from 10 to 1, and then orders the list by column 1.
You will see that, despite using the TopItem statement, the last item of the list is selected (it would be the first one, if I didn't order the list).
The file called "ColumnSortedListView.cs" implements the class (with the same name) derived from ListView, having the OrderColumn method that allows to order the list by the column you want and in the order you want.
The file calles "FormTest.cs" implements a Form with a ColumnSortedListView object inside, to test the class.

"ColumnSortedListView.cs"

Code:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;

class ColumnSortedListView : ListView 
{
	public enum Order
	{
		Ascending,
		Descending
	}

	private int lastColSorted;
	private ColumnSortedListView.Order lastColSortedOrder;

	public ColumnSortedListView()
	{
		AllowColumnReorder = true;

		lastColSorted = 0;
		lastColSortedOrder = ColumnSortedListView.Order.Ascending;
	}

	public int LastColSorted
	{
		get
		{
			return lastColSorted;
		}

		set
		{
			lastColSorted = value;
		}
	}

	public ColumnSortedListView.Order LastColSortedOrder
	{
		get
		{
			return lastColSortedOrder;
		}

		set
		{
			lastColSortedOrder = value;
		}
	}

	protected override void OnColumnClick(ColumnClickEventArgs e)
	{
		base.OnColumnClick (e);
		OrderColumn(e.Column);
	}

    public void OrderColumn()
    {
        OrderColumn(LastColSorted, LastColSortedOrder);
    }

	public void OrderColumn(int col)
	{
		if (lastColSorted != col)
		{
			ListViewItemSorter = new ListViewItemComparer(col, ColumnSortedListView.Order.Ascending);
			Sort();
			lastColSorted = col;
			lastColSortedOrder = ColumnSortedListView.Order.Ascending;
		}
		else
		{
			if (lastColSortedOrder == ColumnSortedListView.Order.Ascending)
			{
				ListViewItemSorter = new ListViewItemComparer(col, ColumnSortedListView.Order.Descending);
				Sort();
				lastColSortedOrder = ColumnSortedListView.Order.Descending;
			}
			else
			{
				ListViewItemSorter = new ListViewItemComparer(col, ColumnSortedListView.Order.Ascending);
				Sort();
				lastColSortedOrder = ColumnSortedListView.Order.Ascending;
			}
		}
	}

	public void OrderColumn(int col, ColumnSortedListView.Order or)
	{
		ListViewItemSorter = new ListViewItemComparer(col, or);
		Sort();
		lastColSorted = col;
		lastColSortedOrder = or;
	}
}

class ListViewItemComparer : IComparer
{
	private int column;
	private ColumnSortedListView.Order order;

	public ListViewItemComparer()
	{
		column = 0;
		order = ColumnSortedListView.Order.Ascending;
	}

	public ListViewItemComparer(int col) 
	{
		column = col;
		order = ColumnSortedListView.Order.Ascending;
	}

	public ListViewItemComparer(int col, ColumnSortedListView.Order or)
	{
		column = col;
		order = or;
	}

    public int Compare(object x, object y)
    {
        // Let's assume that the SubItems are all integer numbers

        ListViewItem lvx = (ListViewItem)x;
        ListViewItem lvy = (ListViewItem)y;

        int ix = Convert.ToInt32(lvx.SubItems[column].Text);
        int iy = Convert.ToInt32(lvy.SubItems[column].Text);

        if (order == ColumnSortedListView.Order.Ascending)
        {
            if (ix < iy)
                return -1;
            else if (ix == iy)
                return 0;
            else
                return 1;
        }
        else
            if (ix > iy)
                return -1;
            else if (ix == iy)
                return 0;
            else
                return 1;
    }
}

"FormTest.cs"

Code:
using System;
using System.Drawing;
using System.Windows.Forms;

class SeparateMain
{
    public static void Main()
    {
        Application.Run(new FormTest());
    }
}

class FormTest : Form
{
    ColumnSortedListView cslv;

    public FormTest()
    {
        this.Size = new Size(250, 280);
        this.CenterToScreen();

        cslv = new ColumnSortedListView();
        cslv.Parent = this;
        cslv.Size = new Size(200, 200);
        cslv.Location = new Point(10, 10);
        cslv.View = View.Details;
        cslv.MultiSelect = true;
        cslv.FullRowSelect = true;
        cslv.HideSelection = false;
        cslv.Columns.Add("Column 0", 95, HorizontalAlignment.Left);
        cslv.Columns.Add("Column 1", 95, HorizontalAlignment.Right);
        cslv.OrderColumn(1, ColumnSortedListView.Order.Ascending);
        PopulateList();
    }

    public void PopulateList()
    {
        cslv.Items.Clear();
        cslv.BeginUpdate();

        for (int i = 1; i <= 10; i++)
        {
            ListViewItem lvi = new ListViewItem(Convert.ToString(i));
            lvi.SubItems.Add(Convert.ToString(10 - i + 1));

            cslv.Items.Add(lvi);
        }

        cslv.EndUpdate();

        cslv.OrderColumn();

//        cslv.Items[0].Selected = true;   // wrong (it doesn't select the item at the top of the list)
        cslv.TopItem.Selected = true;
    }
}
 
Ok, I have discovered an interesting thing, the TopItem property functions, but only after you have loaded the form...
If you add a button in the form and insert the following code in its click event handler, the item at the top of the ListView is selected. The problem is that it should happen when the form is loaded, without any action of the user after it...

Code:
void btn_Click(object sender, EventArgs e)
{
    for (int i = 0; i <= cslv.Items.Count - 1; i++)
        cslv.Items[i].Selected = false;

    cslv.TopItem.Selected = true;
}
 
More than likely, the handle for the form and controls must be created, which only happens after you .Show() the form. And then the Draw() method must be done initially on the listview before you apply the selected method...

so, you can attach to the FormLoad event and set the property there - because both of those methods should have been run at least once. If that doesn't work, do it initially on the VisibleChanged property if the value is set to true.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top