2010-03-04 112 views
7

我目前正在使用winform c#编写一个listview,并且每次点击listview上的空白处, 所选项目都会丢失。防止listview丢失选定的项目

+0

WinForms或WPF?空白空间的权利或以下?你想要发生什么? – Grammarian 2010-03-05 03:09:07

+0

可能重复的[不允许ListView有零选择的项目](http://stackoverflow.com/questions/3255046/disallow-listview-to-have-zero-selected-items) – 2010-07-15 11:45:02

+0

属性... HideSelection = False和FullRowSelect = True – 2015-05-30 14:11:58

回答

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

这只适用于WPF。 – Grammarian 2010-03-05 03:10:10

+1

@Grammarian - 问题没有说明它是WPF,WinForms,ASP,Silverlight还是其他的。我刚刚回答了我刚才在IDE中打开的那个。您应该使用您最喜爱的C#显示技术发布答案! :-) – 2010-03-05 03:46:55

+0

的确是你的权利。它在winforms – EdgarGad 2010-03-05 14:38:43

1

这比WPF更难在的WinForms做。 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; 
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; 
     } 
    } 
+0

这是一个使用最少代码的有效解决方案。 – hfann 2017-02-11 15:54:23

1

你必须从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); 
    } 
} 
+2

相同的答案在这里:http://stackoverflow.com/a/3255191/188926 – Dunc 2013-05-24 15:14:51

7

listview控件有HideSelection属性默认为True。把它做成False,你很好去......在某些情况下,这足够了。

+0

这不是解决发布的问题,他没有问题的项目取消时,它失去了重点。 – Hugoagogo 2013-11-25 03:22:56

+0

更正:他*在*项目取消选择时出现问题。所选项目未被突出显示,因为控件失去选择的项目。 – Suncat2000 2018-02-05 19:51:57