winform ListView应用之分组、重绘图标、网格线 (c# .net winform)
最近在winform应用中需要用到可分组的数据列表功能,DataGridView默认没有提供分组的功能,而OutlookGrid(http://www.codeproject.com/KB/grid/OutlookGrid.aspx)用起来又是相当的麻烦,最后发现了ObjectListView(objectlistview.sourceforge.net),功能相当的强大,强大到我不需要那么多的功能,额~~所以决定参照它的实现,对ListView做一个简单的扩展(注:本文仅针对ListView的View属性为Details)。
首先为ListView添加好列:
listViewEx1.Columns.AddRange(new ColumnHeader[] { new ColumnHeader("列1"), new ColumnHeader("列2"), new ColumnHeader("列3") }); |
分组
这是ListView自带的功能,用起来也很简单,只需要把ShowGroups设置为true(默认为true),再为ListView添加ListViewGroup,并为ListViewItem设置Group即可,代码如下:
ListViewGroup g = new ListViewGroup("分组");listViewEx1.Groups.Add(g);ListViewItem item = new ListViewItem("数据项", g);listViewEx1.Items.Add(item); |
接下来的重绘方法,就需要通过继承ListView并重写OnDrawSubItem(DrawListViewSubItemEventArgs e)方法来实现,在重写此方法之前,必须设置ListView的OwnerDraw属性为true,用于启用重绘。
给ListViewSubItem设置图标
ListView默认可以设置ImageIndex来显示图标,但是只能设置在每个ListViewItem上,即每一行数据只能有一个图标,若要每个ListViewSubItem都能设置图标,则需要通过重写OnDrawSubItem(DrawListViewSubItemEventArgs e)方法来实现,关键代码为:
Graphics g = e.Graphics;Rectangle r = e.Bounds;Rectangle imageBounds = new Rectangle(r.Location, image.Size);//image为具体的图标文件g.DrawImage(image, imageBounds);//通过DrawImage方法绘制图标 |
对这种方法简单的改造,可以为每一列设置单独的图标。
网格线
ListView在设置了分组的情况下,GridLines属性就无效了,所以如果需要显示网格线,也需要通过重写OnDrawSubItem(DrawListViewSubItemEventArgs e)方法来实现,关键代码为:
Graphics g = e.Graphics;Rectangle r = e.Bounds;using (Pen pen = new Pen(Color.Gray)){ g.DrawRectangle(pen, r.X, r.Y, r.Width, r.Height + 1);//高度加1使横向线条重叠} |
以上代码画了灰色的网格线,也可以简单改造以实现自定义的网络线颜色。
选中的背景
在重写OnDrawSubItem(DrawListViewSubItemEventArgs e)方法之后,选中ListView的行,默认的背景色不会出现,所以还得把选中状态的背景色显示出来,关键代码为:
if ((e.ItemState & ListViewItemStates.Selected)== ListViewItemStates.Selected) { using (SolidBrush brush = new SolidBrush(Color.Blue)) { g.FillRectangle(brush, r); } } |
以上代码为选中的列绘制了蓝色的背景,同样也可以扩展以上代码来实现自定义背景色。
呈现原始文本
在重写OnDrawSubItem(DrawListViewSubItemEventArgs e)之后,原来的文本内容同样也会像背景一样丢失了,所以需要把原来的文本重新绘制出来,关键代码如下:
Graphics g = e.Graphics;Rectangle r = e.Bounds;TextRenderer.DrawText( g, e.SubItem.Text, e.SubItem.Font, r, e.SubItem.ForeColor, TextFormatFlags.Left); |
其他
1、自动调整列大小:调用AutoResizeColumns方法,listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent)
2、隐藏列头:设置HeaderStyle属性,listView1.HeaderStyle = ColumnHeaderStyle.None
3、选择整行:设置FullRowSelect为true
4、行双击事件:绑定ListView的MouseDoubleClick事件,代码如下:
void listView1_MouseDoubleClick(object sender, MouseEventArgs e){ ListViewHitTestInfo info = listView1.HitTest(e.Location); if (info != null && info.Item != null) { //... }} |
完整的代码
public class ListViewEx : ListView{ public ListViewEx() : base() { this.OwnerDraw = true;//用于启用重绘 } /// <summary> /// 图标 /// </summary> public Image Icon { get; set; } /// <summary> /// 重绘图标 /// </summary> public bool IsDrawIcon { get; set; } /// <summary> /// 重绘网格线 /// </summary> public bool IsDrawGridLines { get; set; } /// <summary> /// 重绘图标列 /// </summary> /// <param name="e"></param> protected override void OnDrawSubItem(DrawListViewSubItemEventArgs e) { if (View != View.Details || e.ItemIndex == -1) { e.DrawDefault = true; return; } Rectangle r = e.Bounds; Graphics g = e.Graphics; DrawSelectedBackground(e, g, r); int paddingLeft = 0; if (IsDrawIcon) { paddingLeft = this.DrawIcon(g, r, this.Icon, e.Item.BackColor).Width; } if (IsDrawGridLines) { using (Pen pen = new Pen(Color.Gray)) { g.DrawRectangle(pen, r.X, r.Y, r.Width, r.Height + 1);//高度加1使横向线条重叠 } } if (!string.IsNullOrEmpty(e.SubItem.Text)) { this.DrawText(e, g, r, paddingLeft); } } /// <summary> /// 重绘选中时背景 /// </summary> private void DrawSelectedBackground(DrawListViewSubItemEventArgs e, Graphics g, Rectangle r) { if ((e.ItemState & ListViewItemStates.Selected)== ListViewItemStates.Selected) { using (SolidBrush brush = new SolidBrush(Color.Blue)) { g.FillRectangle(brush, r); } } } /// <summary> /// 重绘图标 /// </summary> private Size DrawIcon(Graphics g, Rectangle r, Image image, Color backColor) { Rectangle imageBounds = new Rectangle(r.Location, image.Size); if (image.Height > r.Height) { float scaleRatio = (float)r.Height / (float)image.Height; imageBounds.Width = (int)((float)Icon.Width * scaleRatio); imageBounds.Height = r.Height - 1; } //使图标不会紧贴着每一列的左上角 imageBounds.X += 1; imageBounds.Y += 1; g.DrawImage(image, imageBounds); return imageBounds.Size; } /// <summary> /// 重绘文本 /// </summary> private void DrawText(DrawListViewSubItemEventArgs e, Graphics g, Rectangle r, int paddingLeft) { TextFormatFlags flags = GetFormatFlags(e.Header.TextAlign); r.X += 1 + paddingLeft;//重绘图标时,文本右移 TextRenderer.DrawText( g, e.SubItem.Text, e.SubItem.Font, r, e.SubItem.ForeColor, flags); } /// <summary> /// 获取文本对齐 /// </summary> private TextFormatFlags GetFormatFlags( HorizontalAlignment align) { TextFormatFlags flags = TextFormatFlags.EndEllipsis | TextFormatFlags.VerticalCenter; switch (align) { case HorizontalAlignment.Center: flags |= TextFormatFlags.HorizontalCenter; break; case HorizontalAlignment.Right: flags |= TextFormatFlags.Right; break; case HorizontalAlignment.Left: flags |= TextFormatFlags.Left; break; } return flags; }} |
相关的演示代码:
public Form1(){ InitializeComponent(); ListViewEx listViewEx1 = new ListViewEx(); listViewEx1.Icon = Resources.application; listViewEx1.IsDrawGridLines = true; listViewEx1.IsDrawIcon = true; listViewEx1.Location = new Point(0, 0); listViewEx1.Name = "listViewEx1"; listViewEx1.Size = new Size(284, 265); listViewEx1.Dock = DockStyle.Fill; listViewEx1.FullRowSelect = true; listViewEx1.UseCompatibleStateImageBehavior = false; listViewEx1.View = View.Details; listViewEx1.HeaderStyle = ColumnHeaderStyle.None; listViewEx1.Columns.AddRange(new ColumnHeader[] { new ColumnHeader(), new ColumnHeader(), new ColumnHeader() }); for (int i = 1; i <= 3; i++) { ListViewGroup g = new ListViewGroup("分组" + i.ToString()); listViewEx1.Groups.Add(g); for (int j = 1; j <= 5; j++) { ListViewItem item = new ListViewItem(j.ToString(), g); item.SubItems.Add((i + j).ToString()); item.SubItems.Add((i * j).ToString()); listViewEx1.Items.Add(item); } } this.Controls.Add(listViewEx1);} |
winform ListView应用之分组、重绘图标、网格线 (c# .net winform)的更多相关文章
- WinForm中重绘TabControl选项卡标题
最近开发WinForm频繁使用了TabControl控件,这个控件的选项卡没有BackgroundImage这个属性,那么如何为其各个选项卡添加背景图片呢?(这里说的是每个TabPage的头部,也就是 ...
- 重绘Winform窗体
本文转载自:http://www.cnblogs.com/encoding/p/5603080.html 按照惯例,先来几张样例图(注:为了展示窗口阴影效果,截图范围向外扩展了些,各位凭想象吧). 还 ...
- 【原创】重绘winform的GroupBox
功能:重绘winform的GroupBox,以便调整边框颜色和边框宽度 using System; using System.Collections.Generic; using System.Com ...
- Android重绘ListView高度
Android重绘ListView高度 经常会有这样需求,需要ListView默认将所有的条目显示出来,这就需要外层使用ScrollView,ScrollView里面放置一个重绘高度的ListView ...
- windform 重绘Treeview "+-"号图标
模仿wind系统界面,重绘Treeview + - 号图标 一,首先需要图片 ,用于替换原有的 +-号 二.新建Tree扩展类 TreeViewEx继承TreeView using System; u ...
- 使用重绘项美化WinForm中的控件
如果你觉得项目中的ComboBox.ListBox或其它的Winforms控件不能满足你的显示要求,包括窗体在内很多控件都支持重绘修改显示样式.下面的示例完成对ComBox数据项的重绘,希望能起到抛砖 ...
- [DForm]我也来做自定义Winform之另类标题栏重绘
据说得有楔子 按照惯例,先来几张样例图(注:为了展示窗口阴影效果,截图范围向外扩展了些,各位凭想象吧). 还要来个序 其实,很多年没写过Winform了,前端时间在 ...
- c#winform自定义窗体,重绘标题栏,自定义控件学习
c#winform自定义窗体,重绘标题栏 虽然现在都在说winform窗体太丑了,但是我也能尽量让桌面应用程序漂亮那么一点点话不多说,先上图 重绘标题栏先将原生窗体设置成无边框,FormBoderSt ...
- 『转载』C# winform 中dataGridView的重绘(进度条,虚线,单元格合并等)
原文转载自:http://hi.baidu.com/suming/item/81e45b1ab9b4585f2a3e2243 最近比较浅的研究了一下dataGridView的重绘,发现里面还是有很多东 ...
随机推荐
- [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(4)
这个系列已经写了6篇,链接地址如下: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Auto ...
- 新学C++的for,switch和随机数
通过一个小程序学习: #include<iostream> #include<cstdlib> #include<ctime> using namespace st ...
- 我所理解的readonly和const
最近要给学校软件小组新成员讲几次课,所以把很多以前懒得学习的和模糊不清的知识点,重新学习了一下. MSDN是这样解释的: readonly 关键字与 const 关键字不同. const 字段只能在该 ...
- 用python生成一个导出数据库的bat脚本文件
# 环境: python3.x def getExportDbSql(db, index): # 获取导出一个数据库实例的sql语句 sql = 'mysqldump -u%s -p%s -h%s - ...
- Win10 IoT C#开发 2 - 创建基于XAML的UI程序 及 应用的三种部署方法
Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 上一章我 ...
- Firemonkey 移动平台 Form 显示使用 ShowModal 范例
procedure TForm1.Button1Click(Sender: TObject); begin Form2 := TForm2.Create(Self); Form2.ShowModal( ...
- 几种常见语言的命名空间(Namespace)特性
命名空间提供了一种从逻辑上组织类的方式,防止命名冲突. 几种常见语言 C++ 命名空间是可以嵌套的 嵌套的命名空间是指定义在其他命名空间中的命名空间.嵌套的命名空间是一个嵌套的作用域,内层命名空间声明 ...
- Oracle数据库,用户的创建及表的创建
安装完成之后,打开浏览器,输入https://127.0.0.1:1158/em 链接至登录数据库界面 用户名:sys 口令为安装时设置的密码(一定牢记) 链接身份为:SYSDBA(以系统管理 ...
- linux下安装rzsz
1.登陆linux,下载rzsz安装包 wget http://freeware.sgi.com/source/rzsz/rzsz-3.48.tar.gz 2.tar zxvf rzsz-3.48.t ...
- CMS
一.任务简介: 开发简单的CMS.在数据库中创建新闻数据库表news,包含(题目.作者.日期.正文等字段):创建HTML模板文件:读取数据库所有数据的信息,并使用新闻信息 替换模板文件中的占位符,从而 ...