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

WinForms ListBox动态修改字体及批量设置指定项为粗体的方法

WinForms ListBox动态设置匹配项为粗体(适配搜索场景)

嘿,这个需求我太熟悉了!WinForms的ListBox默认不支持给单个项单独设置字体,但咱们可以用**自绘(Owner-Draw)**的方式搞定,完全适配你这种搜索时动态标记匹配项的场景。下面一步步来实现:

1. 开启ListBox的自绘模式

首先,你需要把ListBox的DrawMode属性设置为OwnerDrawFixed(如果所有项高度一致的话,这个最省事),或者OwnerDrawVariable(如果需要不同高度的项)。可以在设计器里改,也可以在代码里设置:

// 窗体加载时设置
private void Form1_Load(object sender, EventArgs e)
{
    listBox1.DrawMode = DrawMode.OwnerDrawFixed;
}

2. 处理搜索逻辑,动态更新列表

先定义一个变量存储搜索关键词,再在搜索框的TextChanged事件里处理列表排序(把匹配项置顶),并触发ListBox重绘:

private string _searchKeyword = string.Empty;
private List<string> _originalItems; // 保存从文件读取的原始列表

// 加载文件时初始化原始列表
private void LoadItemsFromFile(string filePath)
{
    _originalItems = File.ReadAllLines(filePath).ToList();
    listBox1.Items.AddRange(_originalItems.ToArray());
}

// 搜索框文本变化时触发
private void txtSearch_TextChanged(object sender, EventArgs e)
{
    _searchKeyword = txtSearch.Text.Trim();
    
    if (string.IsNullOrEmpty(_searchKeyword))
    {
        // 搜索为空,恢复原始列表
        listBox1.Items.Clear();
        listBox1.Items.AddRange(_originalItems.ToArray());
    }
    else
    {
        // 分离匹配项和非匹配项,匹配项置顶
        var matchedItems = _originalItems.Where(item => 
            item.IndexOf(_searchKeyword, StringComparison.OrdinalIgnoreCase) >= 0).ToList();
        var unmatchedItems = _originalItems.Except(matchedItems).ToList();
        
        listBox1.Items.Clear();
        listBox1.Items.AddRange(matchedItems.Concat(unmatchedItems).ToArray());
    }
    
    // 刷新ListBox,让它重新绘制每个项的字体
    listBox1.Refresh();
}

3. 重写DrawItem事件,自定义字体绘制

这是核心步骤!在DrawItem事件里,我们可以判断当前项是否匹配搜索关键词,然后决定用粗体还是普通字体绘制:

private Font _boldFont; // 缓存粗体字体,避免频繁创建

private void Form1_Load(object sender, EventArgs e)
{
    listBox1.DrawMode = DrawMode.OwnerDrawFixed;
    // 初始化粗体字体,基于ListBox的默认字体
    _boldFont = new Font(listBox1.Font, FontStyle.Bold);
}

private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    // 防止索引越界(比如ListBox为空时)
    if (e.Index < 0) return;

    // 获取当前项的文本
    string itemText = listBox1.Items[e.Index].ToString();

    // 绘制项的背景:选中项用系统高亮色,否则用ListBox背景色
    e.DrawBackground();

    // 判断当前项是否匹配搜索关键词
    bool isMatch = !string.IsNullOrEmpty(_searchKeyword) && 
                   itemText.IndexOf(_searchKeyword, StringComparison.OrdinalIgnoreCase) >= 0;

    // 选择要使用的字体
    Font itemFont = isMatch ? _boldFont : listBox1.Font;

    // 选择文本颜色:选中项用系统高亮文本色,否则用默认文本色
    Brush textBrush = e.State.HasFlag(DrawItemState.Selected) 
        ? SystemBrushes.HighlightText 
        : SystemBrushes.ControlText;

    // 绘制文本
    e.Graphics.DrawString(itemText, itemFont, textBrush, e.Bounds);

    // 绘制焦点框(如果项获得焦点的话)
    e.DrawFocusRectangle();
}

// 窗体关闭时释放字体资源,避免内存泄漏
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    _boldFont.Dispose();
}

一些注意事项

  • 如果你的ListBox项高度不一致,可以把DrawMode设为OwnerDrawVariable,然后处理MeasureItem事件来设置每个项的高度。
  • 缓存_boldFont是为了避免每次绘制项时都创建新的Font对象,提升性能并减少内存占用。
  • 搜索匹配用了StringComparison.OrdinalIgnoreCase,是不区分大小写的搜索,如果需要区分大小写,改成StringComparison.Ordinal即可。

这样一来,每次你在搜索框输入内容,ListBox不仅会把匹配项置顶,还会自动把这些项显示为粗体,完全满足你的动态需求!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:36:50