【问题标题】:Preventing user selection but allowing selection programmatically阻止用户选择但允许以编程方式选择
【发布时间】:2012-11-27 12:09:50
【问题描述】:

我的 Windows 应用程序中有一个 listview 控件,其中填充了一些项目。我将通过将ListViewItem.Selected 属性设置为true 以编程方式选择项目。但我想阻止用户在列表视图中选择一个项目。即,应始终以编程方式选择它。我可以通过禁用控件来阻止用户选择,但是禁用控件也会禁用不正确的滚动条。

即使我已经创建了一个自定义列表视图控件并使用 WndProc check link 实现了一个 ItemSelectionChanging 事件处理程序,我可以使用它来取消事件,如下所示,

private void lstLiveTables_ItemSelectionChanging(object sender, ListViewExItemSelectionChangingEventArgs e)
{
    e.Cancel = true;
}

但同样,这将取消事件,即使对于以编程方式选择的项目也是如此。我的问题是,无论如何要确定选择是手动(由用户)还是以编程方式在SelectedIndexChanged 或使用WndProc 消息。

注意:如果需要,我会上传CustomListView控件的代码。

更新 1

感谢 emartel。这是个好主意。即使我试图通过仅在选择项目之前订阅事件并在选择后立即将其删除来实现相同的目的。通过这种方式,一旦选择,事件将立即触发并继续。这工作正常。

this.lstTables.SelectedIndexChanged += new System.EventHandler(this.lstTables_SelectedIndexChanged);
item.Selected = true;
this.lstTables.SelectedIndexChanged -= new System.EventHandler(this.lstTables_SelectedIndexChanged);

但我又遇到了一个问题,如果用户手动选择一个项目,则不会发生任何事情(不会触发任何事件),但该项目将被突出显示。一旦一个项目被突出显示,并且如果我尝试以编程方式选择相同的项目,则不会发生任何事情,即,SelectedIndexChanged 事件不会为该项目触发,因为它已经被突出显示。

注意:即使我遵循您建议的 Flag 方法,也会有相同的行为。

更新 2

我可以通过自己的方法解决这个问题,而不是像 emartel 的建议那样通过事件处理。但我的问题是,根据我的更新 1,当项目被突出显示但未被实际选中时,是否仍然会触发 SelectedIndexChanged 事件?

【问题讨论】:

  • 我认为您以错误的方式看待这个问题 - 始终触发并“取消”对框的检查除非您以编程方式执行此操作 - 例如void itemChanging(object sender, ListViewExItemSelectionChangingEventArgs e) { if(!programaticallyChanging) e.Cancel = true; }。然后当以编程方式将programaticallyChanging 更改为true,然后设置'selected' 标志,然后将programaticallyChanging 设置回false
  • 但是 emartel 有一个观点 - 为什么要打扰这个事件呢?事件的重点是在某些动作发生时处理某些事情......如果您在代码隐藏中控制项目的滴答声,为什么不跳过整个事件处理程序?
  • 啊等一下 - 我刚刚意识到我看了你的更新,然后同意 emartels 评论对你不起作用,然后我和自己的大脑斗争了一秒钟,无视最初的想法并替换了它用谎言,然后将谎言发布为评论。我最初的评论应该有效,第二条只是一时的疯狂

标签: c# winforms listview


【解决方案1】:
public FrmTest()
{
    list.ItemSelectionChanged += list_ItemSelectionChanged;
}

private bool changing;

private void list_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
    if (changing)
        return;

    if (e.Item == nonSelectableListItem) 
    {
        changing = true;
        nonSelectableListItem.Selected = false;
        changing = false;
    }
}

示例:

【讨论】:

    【解决方案2】:

    嗯,一个简单的解决方案是保留一个标志,表明您正在以编程方式更改选择并允许事件通过,并在完成后重置标志

    编辑:如果您,并且只有您可以更改选择,并且您以编程方式执行此操作,那么您可以控制在何时何地发生这种情况,为什么要这样做你甚至需要EventHandler?为什么不调用一个方法来做任何你想做的处理?

    【讨论】:

    • 其实我是通过事件来做的,因为它实际上是从另一个事件触发的。无论如何,你是对的,我可以有自己的方法,可以从原始事件中调用。谢谢。
    【解决方案3】:

    这样做的一个方法是保留所选项目的列表并在每次更改时刷新选择而不是您的代码。

    还有一个 ItemSelectionChanged 事件,该事件会针对选择状态已更改的每个项目单独引发。您可能可以在此事件中将选择状态翻转回来。

    你也可以看看Better ListView Express控件。它具有只读模式,因此用户无法更改选择。它的设置非常简单:

    listView.ReadOnly = true;
    

    full version 还支持自定义不可选择的项目。简单设置:

    listView.Items[0].Selectable = false;
    

    使第一个不可选择(由用户)。

    当然,您仍然可以从代码中选择项目。

    下图显示了不可选择的项目(它们用灰色标记):

    【讨论】:

      猜你喜欢
      • 2011-06-13
      • 2016-02-27
      • 2016-07-26
      • 2016-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-18
      相关资源
      最近更新 更多