阻止listview丢失所选项目

时间:2010-03-04 20:08:14

标签: c# winforms listview selection

我目前正在使用winform c#中的listview 每次我点击列表视图上的空白区域, 所选项目丢失。

6 个答案:

答案 0 :(得分:9)

listview控件的HideSelection属性默认为True。把它变成False并且你很高兴...在某些情况下这已经足够了。

答案 1 :(得分:2)

我认为有一个属性可以防止这种情况发生,但现在我找不到了。

你可以试试这个:

private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ListView listView = sender as ListView;
    if (listView.SelectedItems.Count == 0)
        foreach (object item in e.RemovedItems)
            listView.SelectedItems.Add(item);
}

答案 2 :(得分:2)

我完成了这样的事情:

private void lvReads_MouseUp(object sender, MouseEventArgs e)
    {
        if (lvReads.SelectedItems.Count == 0)
            if (lvReads.Items.Count > 0)
                lvReads.Items.Find(currentName, false)[0].Selected = true;
    }

private void lvReads_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (lvReads.SelectedItems.Count == 1)
        {               
            selectedIndex = lvReads.SelectedIndices[0];

            if (currentName != lvReads.Items[selectedIndex].Name)
            {

                //load item
            }

            currentName = lvReads.Items[selectedIndex].Name;
        }
    }

答案 3 :(得分:2)

您必须从ListView类继承并执行一些低级别的消息处理

class ListViewThatKeepsSelection : ListView
{
    protected override void WndProc(ref Message m)
    {
        // Suppress mouse messages that are OUTSIDE of the items area
        if (m.Msg >= 0x201 && m.Msg <= 0x209)
        {
            Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
            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);
    }
}

答案 4 :(得分:1)

这在WinForms中比在WPF中要难得多。 WinForms有一个SelectedIndexChanged事件,它不告诉你任何已经选择的内容, plus 每次选择或取消选择行时都会触发它。

因此,如果选择了一行并且您选择了另一行,则会收到两个SelectedIndexChanged个事件:

  1. 取消选择所选行后的一个
  2. 选择新行时的另一行。
  3. 问题在于,在事件#1期间,ListView没有选择任何内容,您不知道是否会出现将选择第二行的事件#2。

    您可以做的最好的事情是等待应用程序空闲(选择更改后几毫秒),如果列表视图仍未选择任何内容,则放回最后选择的行。

    private void listView1_SelectedIndexChanged(object sender, EventArgs e)
    {
        ListView lv = (ListView)sender;
        if (lv.SelectedIndices.Count == 0)
        {
            if (!this.appIdleEventScheduled)
            {
                this.appIdleEventScheduled = true;
                this.listViewToMunge = lv;
                Application.Idle += new EventHandler(Application_Idle);
            }
        }
        else
            this.lastSelectedIndex = lv.SelectedIndices[0];
    }
    
    void Application_Idle(object sender, EventArgs e)
    {
        Application.Idle -= new EventHandler(Application_Idle);
        this.appIdleEventScheduled = false;
        if (listViewToMunge.SelectedIndices.Count == 0) 
            listViewToMunge.SelectedIndices.Add(this.lastSelectedIndex);
    }
    
    private bool appIdleEventScheduled = false;
    private int lastSelectedIndex = -1;
    private ListView listViewToMunge;
    

答案 5 :(得分:0)

我知道十年前问过这个问题。但是我遇到了同样的问题,并立即找到了一个简单而优雅的解决方案,并真诚地希望与大家分享。

有一个代码(在VB.NET中,但是用C#编写它没什么大问题):

Public Class SettingsBox ' Form that contains ListView (lvScreen)

    Private nScreenTracer As Integer
    Private nSelectedScreen As Integer

    Private Sub lvScreen_ItemSelectionChanged(sender As Object,
                                              e As ListViewItemSelectionChangedEventArgs) Handles lvScreen.ItemSelectionChanged
        If e.IsSelected Then nScreenTracer = e.Item.Index
    End Sub

    Private Sub lvScreen_MouseDown(sender As Object,
                                   e As MouseEventArgs) Handles lvScreen.MouseDown
        nScreenTracer = -1
    End Sub

    Private Sub lvScreen_MouseUp(sender As Object,
                                 e As MouseEventArgs) Handles lvScreen.MouseUp
        If nScreenTracer = -1 Then
            lvScreen.SelectedIndices.Add(nSelectedScreen)
        Else
            nSelectedScreen = nScreenTracer
        End If
    End Sub

End Class

此解决方案适用于单项选择,也可以使用List(Of Integer)进行简单的重新设计以进行多选