Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disallow ListView to have zero selected items

My project is .NET/WinForms.

I have a list view which is always filled with items. I would like it to have selection always. However, if I click on an empty area below list view items, it looses selection.

The list has multiple selection = true and hide selection = false.

like image 365
Alex Avatar asked Jul 15 '10 11:07

Alex


3 Answers

This following works if you do not need multiselect. It has the advantage of not needing to to track which item was last selected.

private void ListViewAny_SelectedIndexChanged(object sender, EventArgs e)
{
    if ((sender as ListView).FocusedItem != null)
    {
        (sender as ListView).FocusedItem.Selected = true;
    }
}
like image 40
Shaun Luttin Avatar answered Oct 31 '22 20:10

Shaun Luttin


You need to prevent the native control from seeing the mouse click so it won't unselect an item. Add a new class to your project and paste the code shown below. Compile. Drop it from the top of the toolbox onto your form, replacing the existing one.

using System;
using System.Drawing;
using System.Windows.Forms;

class MyListView : ListView {
    protected override void WndProc(ref Message m) {
        // Swallow mouse messages that are not in the client area
        if (m.Msg >= 0x201 && m.Msg <= 0x209) {
            Point pos = new Point(m.LParam.ToInt32());
            var hit = this.HitTest(pos);
            switch (hit.Location) {
                case ListViewHitTestLocations.AboveClientArea :
                case ListViewHitTestLocations.BelowClientArea :
                case ListViewHitTestLocations.LeftOfClientArea :
                case ListViewHitTestLocations.RightOfClientArea :
                case ListViewHitTestLocations.None :
                    return;
            }
        }
        base.WndProc(ref m);
    }
}
like image 110
Hans Passant Avatar answered Oct 31 '22 22:10

Hans Passant


Like the others have said, the SelectedIndexChanged event is what you should look at, however you should use it in collaboration with the ItemSelectionChanged event. Here's some code I've just cooked up:

// Holds the last selected index
private int _previousIndex = -1;

// Restores the previous selection if there are no selections
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
    if (listView1.SelectedIndices.Count == 0)
    {
        if (_previousIndex >= 0)
        {
            listView1.SelectedIndices.Add(_previousIndex);
        }
    }
}

// Records the last selected index
private void listView1_ItemSelectionChanged(object sender, 
               ListViewItemSelectionChangedEventArgs e)
{
    if (e.IsSelected)
    {
        _previousIndex = e.ItemIndex;
    }
}

For pure code re-use purposes, it'd probably be worthwhile putting this code into a new UserControl and have a property that determines whether or not to allow the last selection to be lost:

public class CustomListView : ListView
{

    protected CustomListView()
    {
        this.SelectedIndexChanged += new EventHandler(CustomListView_SelectedIndexChanged);
        this.ItemSelectionChanged += new ListViewItemSelectionChangedEventHandler(CustomListView_ItemSelectionChanged);
    }

    void CustomListView_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (this.MaintainLastSelection && this.SelectedIndices.Count == 0)
        {
            if (_previousIndex >= 0)
            {
                this.SelectedIndices.Add(_previousIndex);
            }
        }
    }

    void CustomListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
    {
        if (e.IsSelected)
        {
            _previousIndex = e.ItemIndex;
        }
    }

    private int _previousIndex = -1;

    public bool MaintainLastSelection
    {
        get { return _maintainLastSelection; }
        set { _maintainLastSelection = value; }
    }
    private bool _maintainLastSelection;

}
like image 2
djdd87 Avatar answered Oct 31 '22 22:10

djdd87