【问题标题】:C# ListView - Detecting when the user deselects an item or select a new oneC# ListView - 检测用户何时取消选择项目或选择新项目
【发布时间】:2014-01-22 09:01:51
【问题描述】:

我试图检测用户何时在 ListView 中选择了新项目以及何时取消选择所有内容(通过单击 ListView 上的空白区域),但我很难做到正确。我需要这个来启用或禁用几个“上移项目”和“下移项目”按钮。我认为最好的方法是处理ItemSelectionChanged 事件,所以我有这个,这似乎很明显:

private void lstItems_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) {
    if (e.IsSelected) {
        cmbMoveUp.Enabled = true;
        cmbMoveDn.Enabled = true;
    } else {
        cmbMoveUp.Enabled = false;
        cmbMoveDn.Enabled = false;
    }
}

当用户取消选择所有内容时它工作正常,但问题是当用户选择另一个项目时会触发此事件两次:一次用于取消选择当前项目,另一次用于选择新项目。这导致某些闪烁在“移动项目上方”和“移动项目向下移动”按钮,因为它将首先禁用按钮(因为取消选择当前项),然后再次启用它们(选择新项目)。

有人知道我该如何解决这个问题吗?我的想法已经用完了。

提前致谢。

【问题讨论】:

  • 好的。对困惑感到抱歉。我已经使用过很多次 ListView 并且从不依赖 ItemSelectionChanged 事件; IsSelected 上都没有。我快速搜索了最后一个属性,我看到的所有结果都提到了 WPF。
  • 关于您的问题,您的代码完全符合预期:当发生“跟踪取消选择”(单击 ListView 内的其他位置)时,它会执行给定的操作。您提到的问题是一种不明情况:如果您单击另一个项目,您的代码可以跟踪此更改,但是应该怎么做?发生了两个动作(一个项目被选中,另一个未被选中),应该怎么做?启用还是禁用?因此,您的代码没有问题,但您的想法没有问题。请清楚说明您希望在每种情况下发生什么,您可能会得到一些帮助。
  • 抱歉不是很清楚。正如您所说,代码有效,并且在一天结束时,它会做它应该做的事情。 The "problem" (more of a quirk actually) is that when another item is selected, it will fire one time due to the deselecting of the current item (disabling the buttons) and, right after this, fire once again due to the newly选定的项目,启用按钮。当然,这两个连续事件发生得非常快,但它“慢”到足以让您在每次在列表视图中选择另一个项目时看到按钮被禁用和再次启用。 (续)
  • 如果用户选择了不同的项目(如丢弃两个事件中的第一个或类似的东西),我需要一些方法来禁用按钮但仍然禁用如果用户取消选择所有内容(当事件仅引发一次时)。 PS.:我对在 SO 上发帖很陌生,请让我知道我是否应该编辑 OP 并将此信息添加到那里或保留在这里。
  • 现在清楚多了(请看我的回答)。我确实认为您应该编辑您的问题以清楚地解释您的目标。

标签: c# winforms listview selecteditemchanged


【解决方案1】:

我希望我的列表视图在取消选择列表时禁用两个按钮。下面的代码实现了这一点。

private void Session_List_SelectedIndexChanged(object sender, EventArgs e) {
    bool toggle = true;
    if (Session_List.SelectedItems.Count == 0) {
        toggle = false;
    }

    Selected_Task.Enabled = toggle;   
    Perform_Task.Enabled = toggle;
}

【讨论】:

    【解决方案2】:

    我发现的最佳解决方案是将事件处理程序临时设置为 Application.Idle 并从那里进行检查,如下所示:

    bool handled;
    private void lstItems_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) {
        if (!handled)
        {   handled = true;
            Application.Idle += SelectionChangeDone;   }
    }
    
    private void SelectionChangeDone(object sender, EventArgs e) {
        Application.Idle -= SelectionChangeDone;
        handled = false;
    
        if (lstItems.SelectedItems.Count > 0)
             cmbMoveUp.Enabled = cmbMoveDn.Enabled = true;
        else cmbMoveUp.Enabled = cmbMoveDn.Enabled = false;
    }
    

    使用ItemSelectionChangedSelectedIndexChanged 都没有关系。在这种情况下,两者都可以正常工作。

    非常感谢 Grammarian 在这里回答了基本相同的问题:https://stackoverflow.com/a/26393234/2532220

    【讨论】:

      【解决方案3】:

      我从未使用过 listView,但我认为您可以删除 lstItems_ItemSelectionChanged 方法的 else 部分,然后在 if 部分中您可以先禁用所有按钮,然后仅启用两个相关按钮。 lstItems_ItemSelectionChanged 事件触发两次,第一次“if”不触发,第二次“if”将触发。这样你的问题就解决了。

      【讨论】:

      • 谢谢,但是当用户取消选择所有内容时它不会禁用按钮,因为在这种情况下,e.Select 将是错误的。
      • 控件的名称是 ListView,如果您对给定情况没有任何经验,也许您不应该写答案(在这里询问的人至少希望有知识的程序员,在这个具体的事情上回答)。正如上面答案中所评论的那样,您的“解决方案”没有任何意义,纯粹来说,不值得+1(IMO)。仔细考虑问题(请随时查看我关于 OP 问题的 cmets 以进一步澄清问题)并考虑重新编写您的建议。
      • 我 -1 给你,因为你的回答没有任何意义。至于有人对我的 -1 表示完全正确(+ 这里发生的其他一些非常奇怪的事情),我宁愿不应用我通常应用的规则,并且在这里 -1 一切(因为客观上很糟糕,没有报复全部;通常我是理解的,但在这些条件下理解的意义何在?)。
      【解决方案4】:

      您是否尝试过使用 lstItems_SelectedIndexChanged 而不是 lstItems_ItemSelectionChanged? 我相信这只会触发这 1 次。 希望对您有所帮助!

      【讨论】:

      • 您不理解这里的问题(请随时阅读我上面的 cmets 以澄清您的想法):OP 想要跟踪的行为(每次选择项目时发布的 if-else/ deselected) 意味着当由于选择了不同的项目而取消选择项目时,将到达两次。这里的问题是OP的思路不是太清楚。
      猜你喜欢
      • 1970-01-01
      • 2015-10-19
      • 1970-01-01
      • 2013-07-19
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 2014-08-01
      相关资源
      最近更新 更多