阻止listview丢失所选项目

我目前正在使用winform c#中的listview,每次单击listview上的空白区域时,所选项目都将丢失。

listview控件具有默认为TrueHideSelection属性。 把它False ,你很高兴……在某些情况下,这已经足够了。

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

你可以试试这个:

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

我完成了这样的事情:

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

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

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

  1. 取消选择所选行之后的一个
  2. 选择新行时的另一个。

问题在于,在事件#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; 

您必须从ListView类inheritance并执行一些低级消息处理

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