You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#自定义ListBox控件Click事件无法触发问题求助

自定义UserControl的Click事件未触发的解决方法

问题描述

我实现了一个继承自UserControl的CustomListBox控件,内部封装了ListBox。在窗体中使用该控件(命名为MainLB)并绑定Click事件后,点击控件时MainLB_Click事件未触发,推测点击事件被内部ListBox捕获。请问如何让自定义控件的Click事件正常工作?

CustomListBox实现代码

class CustomListBox : UserControl
{
    //Fields
    private Color borderColor = Color.MediumSlateBlue;
    private int borderSize = 1;

    //Items
    private ListBox Listb;

    //Properties
    [Category("Custom")]
    public Color BorderColor
    {
        get { return borderColor; }
        set
        {
            borderColor = value;
        }
    }

    [Category("Custom")]
    public int BorderSize
    {
        get { return borderSize; }
        set
        {
            borderSize = value;
            this.Padding = new Padding(borderSize);//Border Size
            AdjustListBoxDimensions();
        }
    }

    [Category("Custom")]
    public override Color BackColor
    {
        get { return base.BackColor; }
        set
        {
            this.Listb.BackColor = value;
            base.BackColor = value;
        }
    }

    public void Add(object item)
    {
        this.Listb.BeginUpdate();
        this.Listb.Items.Add(item);
        this.Listb.EndUpdate();
    }

    public void Clear()
    {
        this.Listb.BeginUpdate();
        this.Listb.Items.Clear();
        this.Listb.EndUpdate();
    }

    public int SelectedIndex()
    {
        return this.Listb.SelectedIndex;
    }

    public object Item(int index)
    {
        return this.Listb.Items[index];
    }

    // List Properties
    public CustomListBox()
    {
        Listb = new ListBox();
        this.SuspendLayout();
        // ListBox
        Listb.BorderStyle = BorderStyle.None;
        Listb.DrawMode = DrawMode.OwnerDrawFixed;
        Listb.Font = new Font("Cascadia Mono", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        Listb.ForeColor = Color.FromArgb(((int)(((byte)(249)))), ((int)(((byte)(249)))), ((int)(((byte)(249)))));
        Listb.FormattingEnabled = true;
        Listb.ItemHeight = 24;
        Listb.Location = new Point(0,0);
        Listb.Name = "CustomListBox";
        Listb.Size = new Size(235, 936);
        Listb.DrawItem += new DrawItemEventHandler(Listb_DrawItem);
        Listb.Dock = DockStyle.Fill;
        Listb.BackColor = BackColor;

        Controls.Add(Listb);
        ResumeLayout();
        AdjustListBoxDimensions();
    }

    // Highlight event
    private void Listb_DrawItem(object sender, DrawItemEventArgs e)
    {
        Color backgroundColor = Color.FromArgb(50, 50, 50);
        Color horizontalColor = Color.FromArgb(100, 100, 100);

        if (e.Index >= 0)
        {
            SolidBrush sb = new SolidBrush(((e.State & DrawItemState.Selected) == DrawItemState.Selected) ? horizontalColor : backgroundColor);
            e.Graphics.FillRectangle(sb, e.Bounds);
            string text = Listb.Items[e.Index].ToString();
            SolidBrush tb = new SolidBrush(e.ForeColor);
            e.Graphics.DrawString(text, e.Font, tb, Listb.GetItemRectangle(e.Index).Location);
        }
    }

    //Adjust Dimension (Still in test)
    private void AdjustListBoxDimensions()
    {
        Listb.Location = new Point()
        {
            X = this.Width - this.Padding.Right - Listb.Width,
            Y = Listb.Height
        };
    }

    // Draws the border
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics graph = e.Graphics;
        //Draw border
        using (Pen penBorder = new Pen(borderColor, borderSize))
        {
            penBorder.Alignment = PenAlignment.Inset;
            graph.DrawRectangle(penBorder, 0, 0, this.Width - 0.5F, this.Height - 0.5F);
        }
    }
}

窗体绑定事件代码

private void MainLB_Click(object sender, EventArgs e)
{
    string text = MainLB.Item(MainLB.SelectedIndex()).ToString();
}

解决方法

WinForms中子控件会优先处理鼠标事件,不会自动将事件冒泡到父级UserControl,因此需要手动将内部ListBox的Click事件转发给CustomListBox的Click事件。

具体修改

在CustomListBox的构造函数中,给内部ListBox添加Click事件处理逻辑,触发父控件的OnClick方法:

public CustomListBox()
{
    Listb = new ListBox();
    this.SuspendLayout();
    // 保留原有ListBox配置代码...
    
    // 添加以下代码,转发Click事件
    Listb.Click += (sender, e) => base.OnClick(e);

    Controls.Add(Listb);
    ResumeLayout();
    AdjustListBoxDimensions();
}

原理说明

当用户点击内部ListBox时,会触发Listb的Click事件,通过Lambda表达式调用CustomListBox的OnClick方法,该方法会触发CustomListBox自身的Click事件,从而让窗体中绑定的MainLB_Click事件正常执行。

如果需要同时处理其他鼠标事件(如MouseDoubleClick),可以用同样的方式转发:

Listb.MouseDoubleClick += (sender, e) => base.OnMouseDoubleClick(e);

内容的提问来源于stack exchange,提问作者Filipe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 07:05:22