C# winfrom ListView控件实现自由设置每一行字体及背景色等
背景:公司经常会需要将日志信息,输出到一个对话框中显示出来。之前一直采用的listbox控件,操作简单,使用方便,但是遗憾的是,不能自由控制每一行的状态。
于是想了如下几个方案:
(1)重绘listbox的OnDrawItem函数,这个难度比较大,一顿操作之后,发现实现不了,于是放弃
(2)给每个listbox添加DrawItem事件,这个比较简单,网上也有很多例子。但是针对每个listbox都需要添加相应的事件,操作麻烦且没有通用性。
(3)于是想到了第三个办法,也是最终实现的方法,换成ListView控件
具体实现过程
1.在ListView的默认状态下,输出一行数据,发现会自动换行,将LabelWrap设置为False即可解决
2.当然,选中的时候,我们也希望是一行数据,所以可以将FullRowSelect设置为True。
3.接下来就是尝试Listview控件的view属性了,需要自己不断的尝试,才能找到最好的结果
(1)LargeImage和SmallImage,看似可以正常使用,但是如果字体大小不一样的话,会将每一行数据自动排列(放弃)
(2)list,只有横向滚动条。放弃
(3)tile,不能增加横向滚动条,放弃
(4)最终只有detail有可能达到我们想要的目的
4.在detail下,第一次插入一行数据,会发现数据根本不显示,原因是因为在detail模式下,需要增加一列才可以显示。
5.然后会发现每次更改字体的大小什么的,标题栏也会随之改动,非常的难看,于是将HeaderStyle设置为None,即可将其隐藏起来。
6.因为ListviewItem的宽度固定,如果文字长度较长,会变成省略号,所以就需要计算当前文字的宽度。基本算法如下
Graphics g = Graphics.FromImage(new Bitmap(1, 1)); SizeF s = g.MeasureString(strMessage, font);
其中strMessage为输出的字符串,font为设置的字体,此方法需要用到GDI+的简单只是,因为需要new一个对象,所以建立一个小的即可。
7.关键算法如下
1 ListViewItem lvi = new ListViewItem(); 2 3 lvi.Font = font; 4 lvi.ForeColor = color; 5 lvi.Text = strMessage; 6 7 Graphics g = Graphics.FromImage(new Bitmap(1, 1)); 8 SizeF s = g.MeasureString(strMessage, font); 9 10 if (s.Width > listView.Columns[0].Width) 11 { 12 listView.Columns[0].Width = (int)s.Width + 10; 13 } 14 15 listView.Invoke((EventHandler)(delegate 16 { 17 listView.Items.Insert(0, lvi); 18 19 listView.Font = lvi.Font; 20 21 22 23 int nCount = listView.Items.Count; 24 if (nCount >= 50) 25 { 26 listView.Items.RemoveAt(nCount - 1); 27 } 28 }));
8.最终的实现结果如下: