.Net强大的列表控件XPTable【进阶版】

旧版本

2012年分享过XPTable的一个版本源码,其中包含了我对其若干bug的修正。链接在此:.Net强大的列表控件XPTable

Github上别人的更新

Github最新源码地址:https://github.com/schoetbi/XPTable
XPTable各版本内容

我的最新修改

之前根据1.1修改的版本虽然部分bug得到了解决,但仍有不尽人意的地方,比如依然有隐藏的bug、不支持多级列表展开、不支持皮肤换色、不支持ProgressBarColumn自定颜色、不支持滚动条风格修改、不支持列拖动等。后来2013年下载了一个1.2.2版本源码,有了二级列表即分组功能(Group),但问题多多,包括我之前修正的bug依然存在。没办法,动手术吧。刚统计了一下,前后陆陆续续修改带添加文件共18个,有修改注释的定位有191处,最终达成如下:

  • 修正“遇到”的所有bug
  • .Net2.0及以上各版本均可用
  • 完善修正Group功能(此新功能也bug重重)
  • 支持皮肤换色
  • 支持ProgressBarColumn自定颜色
  • 支持滚动条风格修改并指定滚动条颜色
  • 支持列拖动调整顺序

现在这个XPTable已基本可用。Github上的1.6版本,不知解决了哪些问题增加了哪些新功能,我已不想去探究,因为在改代码的路上走得太远,已无力合并新版版了。

下面给一个示例,设置如下深色风格,进度条颜色可自定,并且group那一行的完成率可以不显示(实际是0%)
深色风格示例
拖动列调整顺序:
拖动列头调整顺序

源码

源码及示例代码下载链接XPTable_Fixed源码及示例代码
示例实现代码如下,展示了如何利用TableCtrl方便使用XPTable,如添加列表头、Group行及其子行、删除行、设置Cell的前景和背景色、高效更新列表等。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.RegularExpressions;

using XPTable;
using XPTable.Models;
using XPTable.Editors;
using XPTable.Renderers;

namespace Test
{
    
    
    public partial class Form1 : Form
    {
    
    
        public Form1()
        {
    
    
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
    
    
            var tbl = table1;
            TableCtrl.InitTable(ref table1);
            table1.AllowMoveHeader = true;                  //允许拖动列表头改变列顺序
            table1.ProgressBarColor = Color.DarkOrange;     //设置ProgressBarColumn进度条的颜色

            /**********设置XPTable颜色风格**********/
            table1.BackColor = Color.FromArgb(50, 50, 70);
            table1.ForeColor = Color.WhiteSmoke;
            table1.AlternatingRowColor = Color.FromArgb(50, 60, 90);

            //表头背景色用渐变风格
            var header = new GradientHeaderRenderer();
            table1.HeaderRenderer = header;
            header.ForeColor = Color.WhiteSmoke;
            header.StartColor = Color.FromArgb(100, 100, 120);
            header.EndColor = table1.BackColor;
            
            //添加Column
            TableCtrl.AddGroupColumn(ref table1, new GroupColumn("", 20));      //添加GroupColumn,parent row会出现一个+号,展开为-号
            TableCtrl.AddColumn(ref table1, new TextColumn("姓名", 90), false, true, ColumnAlignment.Center);
            TableCtrl.AddColumn(ref table1, new TextColumn("性别", 90), false, true, ColumnAlignment.Center);
            TableCtrl.AddNumColumn(ref table1, new NumberColumn("年龄", 60), true, true, false, 0, 100, "#0", ColumnAlignment.Center);
            TableCtrl.AddColumn(ref table1, new TextColumn("院系", 90), false, true, ColumnAlignment.Center);
            TableCtrl.AddNumColumn(ref table1, new NumberColumn("分数", 60), false, true, false, 0, 100, "###,##0.00", ColumnAlignment.Right);

            var pbcol = new ProgressBarColumn("完成率%", 200, true, false); //后俩参数表示显示百分比,但当值为0时不显示
            TableCtrl.AddColumn(ref table1, pbcol, false, true, ColumnAlignment.Center);

            ShowData();
        }

        private void ShowData()
        {
    
    
            table1.BeginUpdate(); //BeginUpdate()和EndUpdate()可以提高列表更新效率,数据更新完后,最后刷新一次,否则每一个数据修改都会触发列表刷新,效率低下。

            var key = "group1";
            var rowGroup = TableCtrl.AddNewRow(ref table1, key);
            TableCtrl.SetTableValue(ref table1, rowGroup, "姓名", "组1");
            for (int i = 1; i < 4; i++)
            {
    
    
                AddChildRow(table1, rowGroup, "小强" + i, "男", 25, "数学系", 50.896 + i * 3, 45.9 + i * 3);
                AddChildRow(table1, rowGroup, "婷婷" + i, "女", 22, "英语系", 98.656, 99 + i);
            }
            rowGroup.ExpandSubRows = true;  //展开Group

            key = "group2";
            rowGroup = TableCtrl.AddNewRow(ref table1, key);
            TableCtrl.SetTableValue(ref table1, rowGroup, "姓名", "组2");
            for (int i = 1; i < 10; i++)
            {
    
    
                AddChildRow(table1, rowGroup, "大熊" + i, "男", 26, "法律系", 70.666 - i * 7, 25 + i);
                AddChildRow(table1, rowGroup, "芳芳" + i, "女", 21, "哲学系", 97.888, 65 + i);
            }

            rowGroup.ExpandSubRows = true;  //展开Group

            table1.EndUpdate();
        }

        private void AddChildRow(Table tbl, Row rowGroup, string name, string gender, int age, string department, double score, double ratio)
        {
    
    
            var key = name;
            var rowChild = TableCtrl.AddNewRow(ref tbl, rowGroup, key);
            TableCtrl.SetTableValue(ref tbl, rowChild, "姓名", name);
            TableCtrl.SetTableValue(ref tbl, rowChild, "性别", gender);
            TableCtrl.SetTableValue(ref tbl, rowChild, "年龄", age);
            TableCtrl.SetTableValue(ref tbl, rowChild, "院系", department);
            TableCtrl.SetTableValue(ref tbl, rowChild, "分数", score);
            TableCtrl.SetTableValue(ref tbl, rowChild, "完成率%", Convert.ToInt32(ratio)); //ProgressBarColumn只支持int型数据

            if (gender == "男")
                TableCtrl.SetCellBackColor(ref tbl, rowChild.Index, "性别", Color.DarkGreen); //设置Cell的背景色
            else
                TableCtrl.SetCellBackColor(ref tbl, rowChild.Index, "性别", Color.DarkRed);   //设置Cell的背景色

            if (score < 60)
                TableCtrl.SetCellForeColor(ref tbl, rowChild.Index, "分数", Color.Red);       //设置Cell的前景色
        }

        private bool IsExist(string name, List<string> names)
        {
    
    
            foreach (var s in names)
            {
    
    
                var r = Regex.Match(name, string.Format(@"^{0}\d+.*", s));
                if (r.Success)
                    return true;
            }
            return false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
    
    
            table1.BeginUpdate();

            //演示如何更新某些行,并删除没更新的行,适用于全量更新列表,删除不再需要的行
            TableCtrl.SetDeleteTag(table1);     //这会改变row.Tag,如果你的row.Tag有他用,则不便这么使用
            var names = new List<string>() {
    
     "小强", "芳芳" };  //保留小强和芳芳所在行
            foreach (Row row in table1.TableModel.Rows)
            {
    
    
                var name = TableCtrl.GetTableValueString(table1, row.Index, "姓名");
                if (IsExist(name, names) || name.IndexOf("组") == 0)
                {
    
    
                    //TODO:根据更新此行数据

                    TableCtrl.RemoveDeleteTag(table1, row.Index);  //避免此行被删除, 也可以直接修改row.Tag,比如row.Tag = name;
                }
            }

            TableCtrl.DeleteRowsByTag(table1); //删除所有要删除的行

            table1.EndUpdate();
        }

        private void button2_Click(object sender, EventArgs e)
        {
    
    
            var key = "婷婷2";
            var row = TableCtrl.GetTableRowByKey(ref table1, key);
            if (row != null)
            {
    
    
                TableCtrl.RemoveRow(ref table1, row);
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
    
    
            TableCtrl.RemoveRowAll(ref table1);
        }
    }
}

Guess you like

Origin blog.csdn.net/bodybo/article/details/117040155