WinForm ListBox中的MouseDown事件会导致SelectedIndexChanged失效

3
我正在编写一些代码,用于检测在MultiSelect模式下的WindForms ListBox中选择的切换。由于SelectedIndexChanged只能让我看到在单击之后所选的内容,因此我正在寻找一种方法来检测在ListBox被单击之前所选的内容。我实现了MouseDown事件,我可以得到我想要的,但一个不幸的副作用是我破坏了SelectedIndexChanged事件,它不会触发。
这是已知的行为吗?有没有关于在单击之前获取选择列表的想法?
谢谢。
编辑以包括代码片段。
设计器生成的事件:
this.lbPhysicianClinic.SelectedIndexChanged += new System.EventHandler( this.lbPhysicianClinic_SelectedIndexChanged );
this.lbPhysicianClinic.MouseDown += new System.Windows.Forms.MouseEventHandler( this.lbPhysicianClinic_MouseDown );

代码片段展示MouseDown事件:

private void lbPhysicianClinic_MouseDown( object sender, MouseEventArgs e )
    {
        List<Clinic_List_ByPhysicianResult> Selected = this.PhysicianGetSelectedClinics( this.lbPhysicianClinic.SelectedIndices );
    }

以下是展示SelectedIndexChanged事件的代码片段:

private void lbPhysicianClinic_SelectedIndexChanged( object sender, EventArgs e )
    {
        try
        {
            if ( this.FormInitComplete && this.RefreshUIComplete )
            {
                List<Clinic_List_ByPhysicianResult> Selected = this.PhysicianGetSelectedClinics( this.lbPhysicianClinic.SelectedIndices );

                Clinic_List_ByPhysicianResult DroppedClinic = new Clinic_List_ByPhysicianResult();

我在每个事件中设置了断点,如果MouseDown事件存在,则SelectedIndexChanged事件永远不会触发。只有当MouseDown事件消失时,它才会触发。

希望这样能更加清晰明了。


你不能通过事件来终止它。你是否在派生类中实际重写了OnMouseDown方法? - Hans Passant
不是。我是通过Visual Studio添加事件的。我在两个事件中都设置了断点,但只有MouseDown事件会触发。当我注释掉MouseDown事件(并从设计器中删除它)时,才会触发SelectedIndexChanged事件。 - Mike Malter
你需要发布一段代码片段。 - Hans Passant
1个回答

5

在引发MouseDown或SelectedIndexChanged事件之前,ListBox会先更改其选择。

您需要做的是捕获底层的Win32消息并自己引发事件。您可以对ListBox进行子类化以实现此操作。

class MyListBox : ListBox
{
    private const int WM_LBUTTONDOWN = 0x201;

    public event EventHandler PreSelect;

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_LBUTTONDOWN:
                OnPreSelect();
                break;
        }

        base.WndProc(ref m);
    }

    protected void OnPreSelect()
    {
        if(null!=PreSelect)
            PreSelect(this, new EventArgs());
    }

}

您可以使用MyListBox类,并添加预选事件的处理程序,如下所示:
this.lbPhysicianClinic.PreSelect += 
    new EventHandler(this.lbPhysicianClinic_PreSelect);

在事件处理程序中,您可以在列表框更改选定索引之前访问它们。


这真是个好主意。有一个小问题需要处理,我该如何从工具箱中拖放它呢?非常感谢。 - Mike Malter
如果您创建了这样的控件,它将出现在工具箱中,是的。它将显示为蓝色齿轮图标。您可能需要重新编译项目,以便设计师可以正确地刷新工具箱。祝你好运! - Edwin Groenendaal

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