Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 防止listview丢失所选项目_C#_Winforms_Listview_Selection - Fatal编程技术网

C# 防止listview丢失所选项目

C# 防止listview丢失所选项目,c#,winforms,listview,selection,C#,Winforms,Listview,Selection,我目前正在winform c中处理listview 每次我点击listview上的空白处, 所选项目丢失。我以为有一个属性阻止了这种情况的发生,但现在我找不到它 你可以试试这个: private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { ListView listView = sender as ListView; if (listView.SelectedItems.

我目前正在winform c中处理listview 每次我点击listview上的空白处,
所选项目丢失。

我以为有一个属性阻止了这种情况的发生,但现在我找不到它

你可以试试这个:

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

在WinForms中比在WPF中更难做到这一点。WinForms有一个SelectedIndexChanged事件,它不会告诉您已经选择了什么,而且每次选择或取消选择一行时都会触发该事件

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

取消选择选定行后的一个 当选择新行时,将显示另一个。 问题是,在事件1期间,ListView没有选择任何内容,并且您不知道事件2是否将选择第二行

您所能做的最好的事情就是等待应用程序在选择更改后几毫秒处于空闲状态,如果listview仍然没有选择任何内容,请放回最后选择的行

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;

我是这样完成的:

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


您必须从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);
    }
}

listview控件具有默认为True的HideSelection属性。把它弄错,你就可以走了。。。在某些情况下,这就足够了

我知道10年前有人问过这个问题。但我面对同样的问题,刚刚找到了一个简单而优雅的解决方案,我真诚地想与大家分享

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

此解决方案适用于单个项目选择,但也可以简单地使用ListOf Integer重新设计多选择

WinForms或WPF?右边还是下面是空白?您希望发生什么?可能存在重复的属性。。。HideSelection=False和FullRowSelect=True@Grammarian-问题没有具体说明是WPF、WinForms、ASP、Silverlight还是其他。我只是用我当时碰巧在IDE中打开的一个来回答。你应该用你最喜欢的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