WinForm常用功能备忘
##更新历史:
- 2012-11-22 » 创建文章,DataGridView,调整单元格样式后排序…
- 2012-12-10 » 增加ListView,关于ListView排序的众多问题
##DataGridView
在WinForm中,DataGridView是常用列表显示控件,也是相对复杂的一个控件,对于经常做管理软件的开发者,DataGridView也是打交道最多的一个。 这里记录本人在实际开发中使用DataGridView的一些备忘。
###调整单元格样式后排序或其他方式使控件刷新而丢失样式的问题
很多软件都有这么一个需求:对于异常数据或特殊数据进行高亮显示。
如一个超限软件,对于超限率不同的检测车辆进行不同的颜色显示;又如某设备管理软件,对于即将维保、年检的设备进行黄色提示,对于已过维保期的设备进行红色提示等等。
本人在做的时候,都是在绑定数据后,循环遍历一次数据,判断某列的值是否符合某种标准,否则给予标注。
以前做法:
void BindData()
{
//BindData...
for(int i = 0; i < dataGridView1.Rows.Length; i++)
{
if(dataGridView.Rows[i].Cells["停用标识"].Value.ToString() == "启用")
{
dataGridView.Rows[i].Cells["停用标识"].Style.BackColor = Color.Red;
}
}
}
但随后发现如果点击排序,都会丢失之前设置的样式。 对于这种不是很影响功能的问题,当初我都不怎么在意,或者对于不是很需要排序功能的直接禁止其排序。(这种思想是不是很不好……)
但问题终归是问题,最后还是得解决。 注册CellFormatting事件,在其中进行判断。
代码如下:
void dataGridView1_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e)
{
if(e.ColumnIndex = 7 && e.Value.ToString() == "启用")
{
e.CellStyle.BackColor = Color.Red;
}
}
##ListView
相较DataGridView而言,ListView在WinForm开发中比较灵活,列表可以实现,带图标的排列也没问题,而且做一些效果也是不错。ListView显然没有DataGirdView封装的那么”严实”,也正是因为这个问题,很多看似简单的功能在ListView中实现很难。
###关于ListView排序的众多问题
最近需要在软件中增加FTP功能,说是简单的功能,但是做起来也遇到了不少问题。主要问题就是目录浏览的问题,如何从FTP返回的列表中分割出大小、修改时间等也是当初没有想到的。而在列表展示上使用ListView控件的主要原因就是ListView控件”添加”数据比较自然,而DataGridView更多的是”绑定”数据。
随后发现ListView没有排序功能。
其实排序功能还是有的,只不过需要自己给定一个比较器。
listView1.ListViewItemSorter = XXXComparer.Instance(XXXComparer : IComparer)
这就是我FTP的窗口。只显示了文件名、大小和修改时间,文件名中目录使用[目录名]
的方式展示,文件名的排序方式按道理上来讲应该是向上、目录、文件这种顺序。大小和修改时间就不用多说了。
这时候,问题就出来了:ListView的项(SubItem
)没有数据类型一说。
对此,给我ListViewSubItem增加了一个强类型的ListViewSubItem:
/// <summary>
/// 强类型ListViewSubItem
/// </summary>
/// <typeparam name="T"></typeparam>
public class ListViewTypeSubItem<T> : ListViewItem.ListViewSubItem
{
public ListViewTypeSubItem()
{
ValueType = typeof(T);
}
public Type ValueType { get; set; }
public T Value { get; set; }
}
当然,这个所谓的强类型还是有一定的问题。暂时这么着吧。
有了强类型的 ListViewSubItem 那么给ListView赋值就要有相应的修改。
foreach (var file in files)
{
lvi = new ListViewItem(file.IsDirectory ? string.Format("[{0}]", file.Name) : file.Name);
size = new ListViewTypeSubItem<long>();
size.Text = file.Size.ToString("N0");
size.Value = file.Size;
lvi.SubItems.Add(size);
date = new ListViewTypeSubItem<DateTime>();
date.Text = file.CreateTime.ToString("yyyy-MM-dd HH:mm");
date.Value = file.CreateTime;
lvi.SubItems.Add(date);
lvi.Tag = file.IsDirectory ? FileTypeEnum.Directory : FileTypeEnum.File;
lvFtpFile.Items.Add(lvi);
}
当然,重要的比较器还没有写。这里列出我写的比较器,其中应该有点问题,因为当初没有想让他能点两次。也就是说没有想让他支持点一次是asc
,再点一次就是desc
。本来只是想做个排序,让大小和修改时间逆序排,而文件名就按我上面说的规则排列。最后需求有所变动。
说了半天,列出我的比较器:
/// <summary>
/// ListViewItem自定义排序
/// 对long类型和DateTime类型进行处理(DESC)
/// 对于字符串,目录排在文件上面,向上排在最上边
/// </summary>
public class ListViewItemComparer : IComparer
{
private static int col;
private static bool isDesc = false;
public ListViewItemComparer(int column)
{
col = column;
}
public int Compare(object x, object y)
{
int result = 0;
var sub = ((ListViewItem)x).SubItems[col];
if (sub is ListViewTypeSubItem<long>)
{
var sub_x = ((ListViewItem)x).SubItems[col] as ListViewTypeSubItem<long>;
var sub_y = ((ListViewItem)y).SubItems[col] as ListViewTypeSubItem<long>;
if (sub_x.Value > sub_y.Value)
{
result = 1;
}
else if (sub_x.Value == sub_y.Value)
{
result = 0;
}
else
{
result = -1;
}
}
else if (sub is ListViewTypeSubItem<DateTime>)
{
var sub_x = ((ListViewItem)x).SubItems[col] as ListViewTypeSubItem<DateTime>;
var sub_y = ((ListViewItem)y).SubItems[col] as ListViewTypeSubItem<DateTime>;
result = DateTime.Compare(sub_y.Value, sub_x.Value);
}
else
{
string sub_x = ((ListViewItem)x).SubItems[col].Text;
string sub_y = ((ListViewItem)y).SubItems[col].Text;
if ((sub_x[0] == '[' && sub_x[sub_x.Length - 1] == ']') &&
(sub_y[0] != '[' || sub_y[sub_y.Length - 1] != ']'))
{
return -1;
}
else
{
result = string.Compare(sub_x, sub_y);
}
}
var lvi_x = (ListViewItem)x;
var lvi_y = (ListViewItem)y;
if (lvi_x.Text == "[..]")
{
return -1;
}
//if (lvi_y.Text == "[..]")
//{
// return isDesc ? 1 : -1;
//}
return isDesc ? result : result == 0 ? 0 : result == 1 ? -1 : 1;
}
public static ListViewItemComparer Sort(int column = 0)
{
isDesc = !isDesc;
return new ListViewItemComparer(column);
}
}
应该从代码中更能感觉到曾经改过的样子。
自我感觉上面的return isDesc ? result : result == 0 ? 0 : result == 1 ? -1 : 1;
一定会有人说。哈哈。
blog comments powered by Disqus