取消 ListBox 的 SelectedIndexChange 事件

17

在WinForms应用程序中,是否可以取消ListBox的SelectedIndexChange事件?这似乎是一个很有道理的功能,我可能忽略了一些简单的特性。基本上,我一直弹出一个消息框,询问用户是否真的想移动到另一个项目,因为这将改变UI,我不想让他们的更改丢失。如果用户没有保存他们正在处理的内容,我希望能够取消事件。是否有更好的方法来做到这一点?


我同意Nawfal的看法,更多细节请查看以下链接: http://www.mindstick.com/Articles/176c6d68-ceca-4072-a319-7389f4e5b9dd/?ListBox%20events%20in%20C%20#.Net - user938256
可能是如何在C#中防止/取消ComboBox的值更改?的重复问题。 - Jim Fell
6个回答

19

你无法取消它。

几天前我做的是有一个变量来存储最新选中的索引。当事件触发时,你可以在事件处理程序中询问用户是否要保存。如果用户选择“取消”,则再次更改id。

问题是这会再次触发事件。所以我使用了一个布尔值,只是说“禁止”。并且在事件处理程序的顶部,我有:

if(Inhibit)
   return;

然后在您提出问题的下方,您可以执行以下操作:

DialogResult result = MessageBox.Show("yadadadad", yadada cancel etc);
if(result == DialogResult.Cancel){
   Inhibit = true; //Make sure that the event does not fire again
   list.SelectedIndex = LastSelectedIndex; //your variable
   Inhibit = false; //Enable the event again
}
LastSelectedIndex = list.SelectedIndex; // Save latest index.

2
在阅读这个答案后,我发现了一个微小的变化 - 你可以删除事件处理程序而不是使用Inhibit标志:list.SelectedIndexChanged -= list_SelectedIndexChanged; list.SelectedIndex = LastSelectedIndex; list.SelectedIndexChanged += list_SelectedIndexChanged;可能有一些原因使这种方法劣于其他方法,但对于我的目的来说非常有效。 - TwainJ
@J Jones 如果您进行了两次减法,会发生什么情况?不确定是否会引发异常? - Oskar Kjellin
@OskarKjellin 你不会重复执行它,因为这是在函数内部。直到你稍后再添加它之前,该函数将不会被再次调用。 - Grungondola

11

这正是@Oskar Kjellin的方法,但有了变化。也就是说,少了一个变量,并且有一个真正像所选索引更改事件的所选索引更改事件。我经常想知道为什么即使我点击完全相同的所选项,所选索引更改事件仍然会触发。在这里不会。是的,这是一个偏差,所以如果您想要它,请再三确认。

    int _selIndex = -1;
    private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (listBox1.SelectedIndex == _selIndex)
            return;

        if (MessageBox.Show("") == DialogResult.Cancel)
        {
            listBox1.SelectedIndex = _selIndex;
            return;
        }

        _selIndex = listBox1.SelectedIndex;
        // and the remaining part of the code, what needs to happen when selected index changed happens
    }

7

我刚遇到了这个问题。当用户进行更改时,我将ListBox.Enabled = false;设置为禁用,这样他们就无法选择其他索引。一旦他们保存或放弃更改,我将ListBox.Enabled = true;设置回启用状态。可能不像提示那样酷,但它能完成工作。


这太棒了。每当我开始担心私有成员变量来跟踪当前索引,或者跟踪某个抑制布尔值时,我就会想:如何避免添加这个额外的逻辑层?禁用ListBox就可以解决这个问题。 - JustLooking

6
更优雅的方式是使用标签属性(Tag property):
        if ((int)comboBox.Tag == comboBox.SelectedIndex)
        {
            // Do Nothing
        }
        else
        {
            if (MessageBox.Show("") == DialogResult.Cancel)
            {
                comboBox.SelectedIndex = (int)comboBox.Tag;
            }
            else
            {
                // Reset the Tag
                comboBox.Tag = comboBox.SelectedIndex;

                // Do what you have to
            }
        }

1
真棒。简单、直接和无误。 - Stefanos Zilellis

2

SelectedIndexChanged事件无法被取消。因此,您只有一个真正的选择:

private int? currentIndex;
public void ListBox_SelectedIndexChanged(sender, EventArgs args) {
    if (currentIndex.HasValue && currentIndex.Value != listBox1.SelectedIndex) {
        var res = MessageBox.Show("Do you want to cancel edits?", "Cancel Edits", MessageBoxButtons.YesNo);
        if (res == DialogResult.Yes) {
            currentIndex = (listBox1.SelectedIndex == -1 ? null : (int?) listBox1.SelectedIndex);
        } else {
            listBox1.SelectedIndex = currentIndex.Value;
        }
    }
}

0

这是我取消ComboBox的SelectionChange的方法。我认为它也适用于ListBox。

private bool comboBox_CancelSelection = false;
private int comboBox_LastSelectedIndex = -1;

private void comboBox_SelectedIndexChanged(object sender, EventArgs e) {
    if (comboBox_CancelSelection) {
        comboBox_CancelSelection = false;
        return ;
    }

    // Handle Event

    if (!comoBox_CancelSelection) {
        comboBox_LastSelectedIndex = comboBox.SelectedIndex; 
    } else {
        comboBox.SelectedIndex = comboBox_LastSelectedIndex;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接