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
相关产品推荐
相关产品推荐

