DataGridView 控件分页

这篇具有很好参考价值的文章主要介绍了DataGridView 控件分页。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在使用Winform开发桌面应用时,工具箱预先提供了丰富的基础控件,利用这些基础控件可以开展各类项目的开发。但是或多或少都会出现既有控件无法满足功能需求的情况,或者在开发类似项目时,我们希望将具有相同功能的模板封装成一个标准控件等,在这些场景下,winform自带的控件就有些乏力了,需要我们自己开发一些控件。

本篇开篇于DataGridView控件的分页效果,当数据量大的时候,分页是必要的,但是控件本身是没有分页功能的,所以需要自己实现。

我不是专业的控件开发人员,所以写下这篇文章作为学习过程中的记录。

前言

.NET提供了丰富的控件创作技术,自定义控件主要分为三类 - Windows Forms Control Development Basics:

  • 复合控件:将现有控件组合成一个新的控件
  • 扩展控件:在现有控件的基础上修改原有控件功能或添加新的功能
  • 自定义控件:从头到尾开发一个全新的控件。继承System.Windows.Forms.Control类,添加和重写基类的属性、方法和事件。winform的控件都是直接或间接从System.Windows.Forms.Control派生的类,基类Control提供了控件进行可视化所需要的所有功能,包括窗口的句柄、消息路由、鼠标和键盘事件以及许多其他用户界面事件。自定义控件是最灵活也最为强大的方法,同时对开发者的要求也比较高,你需要处理更为底层的Windows消息,需要了解GDI+技术以及Windows API

由易到难,我们从最简单的复合控件一步一步来,自定义控件作为我们的终极目标哈😎

通过MSND上的 ctlClockLib 示例学一下怎样开发复合控件以及扩展现有控件:

复合控件 - 示例

来看看怎样创建和调试自定义控件项目,以MSND上的ctlClockLib 中的 ctlClock为例:

  1. 创建Windows 窗体控件库 DataGridView 控件分页

  2. 之后其实和开发Winform项目差不多,在设计时里拖入想要组合的控件,在后台代码实现相应的内容。具体代码,不做赘述,和文档相同。这个教程只要是完成一个可以自定义底色以及时间字体颜色的以及时钟控件,由一个Label和一个Timer组成,暴露出一个ClockBackColor属性和ClockBackColor分别控制背景色以及字体颜色:

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    
    namespace ctlClockLib
    {
        public partial class ctlClock : UserControl
        {
            private Color colFColor;
            private Color colBColor;
    
            public Color ClockBackColor
            {
                get => colBColor;
                set
                {
                    colBColor = value;
                    lblDisplay.BackColor = colBColor;
                }
            }
            public Color ClockBackColor
            {
                get => colFColor;
                set
                {
                    colFColor = value;
                    lblDisplay.ForeColor = colFColor;
                }
            }
            public ctlClock()
            {
                InitializeComponent();
            }
            protected virtual void timer1_Tick(object sender, EventArgs e)
            {
                lblDisplay.Text = DateTime.Now.ToLongTimeString();
            }
        }
    }
    
  3. 运行以后是一个类似设计器的页面,右侧为控件属性,左侧为控件内容:

    DataGridView 控件分页

这样一个简单的复合控件 - ctlClock就完成了,怎么在实际项目中使用就和调用第三方控件是相似的:

  1. 新建一个新的Winform工程:

    DataGridView 控件分页

  2. 在工具箱新建一个选项卡,然后选择项添加上面时钟控件生成的DLL文件,或者直接将文件拖入选项卡中:

DataGridView 控件分页

DataGridView 控件分页

  1. 然后就和正常控件一样用就可以了,这个时钟控件,你拖入可以发现他在设计器里也是会正常走时间的,之后调整自定义的时钟控件就可以在使用控件的窗体中显现出来。

DataGridView 控件分页

扩展控件 - 示例

上面示例中创建了一个名为ctlClock的时钟控件,它只有钟表功能,怎样让它带有报警的功能呢,给ctlClock添加报警功能的过程就是拓展控件的过程。这里需要我们有一些C# 面向对象 - 继承的基础,以MSDN上的 ctlAlarmClock为例。

简单说一下继承:一个类型派生于一个基类型,它拥有该基类型的所有成员字段和函数。在实现继承中,派生类型采用基类型的每个函数的实现代码,除非在派生类型的定义中指定重写某个函数的实现代码。一般在需要给现有类型添加功能时使用继承。

具体编码就不说了,MSDN上都有,在原有ctlClock基础上,添加了一个指示报警的Label:lblAlarm,并重写了ctlClocktimer1_Tick

using System;
using System.Drawing;

namespace ctlClockLib
{
    public partial class ctlAlarmClock : ctlClock
    {
        private DateTime dteAlarmTime;
        private bool blnAlarmSet;
        private bool blnColorTicker;
        public ctlAlarmClock()
        {
            InitializeComponent();
        }

        public DateTime AlarmTime { get => dteAlarmTime; set => dteAlarmTime = value; }
        public bool AlarmSet { get => blnAlarmSet; set => blnAlarmSet = value; }
        protected override void timer1_Tick(object sender, EventArgs e)
        {
            base.timer1_Tick(sender, e);// 基类中的timer1_Tick功能正常运行
            if (AlarmSet == false)
                return;
            else
            {
                if (AlarmTime.Date == DateTime.Now.Date && AlarmTime.Hour ==
                    DateTime.Now.Hour && AlarmTime.Minute == DateTime.Now.Minute)
                {
                    lblAlarm.Visible = true;
                    if (blnColorTicker == false)	// 根据blnColorTicker交替改变lblAlarm背景颜色
                    {
                        lblAlarm.BackColor = Color.Red;
                        blnColorTicker = true;
                    }
                    else
                    {
                        lblAlarm.BackColor = Color.Blue;
                        blnColorTicker = false;
                    }
                }
                else
                {
                    lblAlarm.Visible = false;
                }
            }
        }
        private void lblAlarm_Click(object sender, EventArgs e)
        {
            AlarmSet = false;
            lblAlarm.Visible = false;
        }
    }
}

项目结构:

DataGridView 控件分页

ctlTestDemo设计器:

DataGridView 控件分页

运行ctlTestDemo:

DataGridView 控件分页

回到正题,有了上面例子的基础,来尝试一下通过复合控件实现DataGridView 分页功能。

SuperGridView

参照 C# datagridview分页功能 - 没事写个Bug - 非自定义控件 做了一些优化,可以自定义数据源,做了控件大小自适应处理(就是通过TableLayout做了下处理),控件名 - SuperGridView:

DataGridView 控件分页

控件样式如上图所示,通过TableLayout做了自适应的处理:

DataGridView 控件分页

暴露一个DataSource属性用于给DataGridView绑定数据源,一个PageSize属性可以调整DataGridView每页显示的数据量,控件代码:

DataGridView 控件分页

using System;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;

namespace cassControl
{
    public partial class SuperGridView : UserControl
    {
        private int pageSize = 30;  // 每页记录数
        private int recordCount = 0;    // 总记录数
        private int pageCount = 0;  // 总页数
        private int currentPage = 0;    // 当前页数
        private DataTable originalTable = new DataTable();  // 数据源表
        private DataTable schemaTable = new DataTable();  // 虚拟表

        public SuperGridView()
        {
            InitializeComponent();
            InitializeDataGridzview();
        }

        private void InitializeDataGridzview()
        {
            dgv.AutoGenerateColumns = true;
            dgv.AllowUserToAddRows = false;
            dgv.AllowUserToResizeRows = false;
            dgv.ReadOnly = true;
            dgv.RowHeadersVisible = true;
            dgv.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            dgv.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
        }

        [Category("DataSource"), Description("指示 DataGridView 控件的数据源。")]
        public object DataSource
        {
            get { return OriginalTable; }
            set
            {
                if (value is DataTable dt)
                {
                    OriginalTable = dt;
                    dgv.DataSource = dt;
                    PageSorter();
                }
                else
                {
                    throw new ArgumentException("Only DataTable is supported as DataSource.");
                }
            }
        }
      
        [Category("PageSize"), Description("指示 DataGridView 控件每页数据量。")]
        public int PageSize { get => pageSize; set => pageSize = value; }
        private int RecordCount { get => recordCount; set => recordCount = value; }
        private int PageCount { get => pageCount; set => pageCount = value; }
        private int CurrentPage { get => currentPage; set => currentPage = value; }
        private DataTable OriginalTable { get => originalTable; set => originalTable = value; }
        private DataTable SchemaTable { get => schemaTable; set => schemaTable = value; }

        private void PageSorter()
        {
            RecordCount = OriginalTable.Rows.Count;
            this.lblCount.Text = RecordCount.ToString();

            PageCount = (RecordCount / PageSize);

            if ((RecordCount % PageSize) > 0)
            {
                PageCount++;
            }

            //默认第一页
            CurrentPage = 1;

            LoadPage();
        }

        private void LoadPage()
        {
            if (CurrentPage < 1) CurrentPage = 1;
            if (CurrentPage > PageCount) CurrentPage = PageCount;

            SchemaTable = OriginalTable.Clone();

            int beginRecord;
            int endRecord;

            beginRecord = PageSize * (CurrentPage - 1);
            if (CurrentPage == 1) beginRecord = 0;
            endRecord = PageSize * CurrentPage - 1;
            if (CurrentPage == PageCount) endRecord = RecordCount - 1;

            int startIndex = beginRecord;
            int endIndex = endRecord;
            for (int i = startIndex; i <= endIndex; i++)
            {
                DataRow row = OriginalTable.Rows[i];
                SchemaTable.ImportRow(row);
            }

            dgv.DataSource = SchemaTable;
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            if (CurrentPage == PageCount)
            { return; }
            CurrentPage++;
            LoadPage();
        }

        private void btnBegain_Click(object sender, EventArgs e)
        {
            if (CurrentPage == 1)
            { return; }
            CurrentPage = 1;
            LoadPage();
        }

        private void btnEnd_Click(object sender, EventArgs e)
        {
            if (CurrentPage == PageCount)
            { return; }
            CurrentPage = PageCount;
            LoadPage();
        }

        private void btnPre_Click(object sender, EventArgs e)
        {
            if (CurrentPage == 1)
            { return; }
            CurrentPage--;
            LoadPage();
        }
    }
}

控件功能:

  1. 控件具有自定义的数据源绑定功能,通过 DataSource 属性绑定 DataTable 对象作为数据源。
  2. 控件支持分页显示,可以按照每页固定的记录数显示数据。
  3. 控件的分页功能包括跳转到第一页、上一页、下一页、最后一页,以及显示总记录数等。
  4. 控件中的数据表格 (DataGridView) 可以自动生成列,表中内容默认居中显示

实机演示 - 也还凑合,试了一下自造了十万条数据,但是在十万条数据下可以明显看到内存暴涨,从最初的22MB涨到了60MB😂,好在我的应用场景下数据量不大:

DataGridView 控件分页

这段代码只实现了一个简单的分页数据表格控件,适合处理中小规模的数据。它的主要优点是简化数据绑定和提供分页显示,但仍有改进空间,尤其在处理大数据集和功能扩展方面。如果只是在项目中使用,且数据量不大,这个控件可能已经足够。然而,如果需要更多功能和性能优化,可能需要进一步开发和优化,比如可以加上页面,页码自动跳转之类的,还有内存占用问题等,还有就是在设计器里不能暴露出来DataGridView 任务操作选项,需要通过后台代码完成数据显示的绑定,我在想是不是可以不直接用DataGridView呢,只用下方的操作栏呢?

PagerControl

用上面的思路试一试组合一个操作栏出来,为了好看一点,这次换成组合CSkin的控件。

样式和上面几乎一致,没有放每页条数的配置项,这个打算作为一个属性放出来:

DataGridView 控件分页

我的思路是给控件一个数据源,用于绑定页面中的DataGridView,然后获取到数据以后和之前一样,因为使用场景下数据量不是特别大,所以就同样沿用上面的思路。

这里需要暴露一个配置项用于绑定页面上的DataGridView需要用到设计时的一些特性(Attribute),这些设计时的特性(Attribute)在C#和类似的语言中扮演着非常重要的角色,用于影响控件在设计时的表现和行为,提供更好的用户体验和开发者便利:

DataGridView 控件分页

  • Windows 窗体控件中的特性

OK,理想很丰满,现实很骨感。通过绑定绑定页面中的DataGridView获取数据会有一个问题,因为我控制分页的方式是通过给DataGridView更换处理之后的DataSource数据表,这就导致有一个问题是我不知道DataGridView什么时候会绑定数据,解决这个问题我能想到的就是监听数据源的变化,也就是通过DataGridViewDataSourceChanged事件,但这就导致我在实现分页效果的时候也会触发该事件,逻辑会陷入一个死循环里面。。。

换一种方式,清空DataGridView表中数据然后一行一行的加Clear()方法又会报错:

// 假设已经有一个DataGridView控件名为dataGridViewToBind
// 假设已经有一个DataTable名为newDataTable

// 清空表格中的内容
dataGridView1.Rows.Clear(); 
dataGridView1.Refresh();

// 添加新的DataTable数据
foreach (DataRow row in newDataTable.Rows)
{
    dataGridViewToBind.Rows.Add(row.ItemArray);
}

一通抓耳挠腮之后,我觉得换一种思路:只操作DataGridView上显示的内容,当然也是通过更改它的DataSource来完成,获取DataGridView的数据源采用之前的思路,控件给一个数据源属性,每次更改DataGridView的数据源的时候也顺路操作一下控件的数据源,这样就不用在控件内部监听DataGridView数据源的变化了,也就不会出现我在操作DataGridView的时候程序陷入死循环的问题。

All Right。来说说怎么搞的,更之前那个相比有点不一样,因为是给一个n年前的winform项目做的,所以这里DataGridView改为CSkinSkinDataGridView还有就是数据源,程序用的DataTable这里也就用``DataTable了,但是数据源那里放的object`类型,可以扩展其他类型数据:

DataGridView 控件分页

using CCWin.SkinControl;
using System;
using System.ComponentModel;
using System.Data;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace cassControl
{
    public partial class PagerControl : UserControl
    {
        public PagerControl()
        {
            InitializeComponent();
        }

        #region fields, properties

        private int pageCount;
        private int dataCount;
        private int pageSize = 50;
        private int currentPage;

        private DataTable dataSourceTable;
        private DataTable tempTable;

        private SkinDataGridView dataGridViewToBind;

        [Browsable(true)]
        [Category("PagerControl")]
        [Description("为 PagerControl 绑定 DataGridView 数据项")]
        public SkinDataGridView DataGridView
        {
            get { return dataGridViewToBind; }
            set
            {
                dataGridViewToBind = value;
            }
        }

        [Browsable(false)]
        public object DataSource    // 数据类型可以扩展
        {
            get { return dataSourceTable; }
            set
            {
                if (value is DataTable dt)
                {
                    dataSourceTable = dt;
                    PageSorter();
                }
                else
                {
                    return;
                }
            }
        }

        [Browsable(false)]
        public int CurrentPage { get => currentPage; set => currentPage = value; }

        [Browsable(false)]
        public int PageCount { get => pageCount; set => pageCount = value; }

        [Browsable(false)]
        public int DataCount { get => dataCount; set => dataCount = value; }

        [Browsable(true)]
        [Category("PagerControl")]
        [Description("设置每页显示的数据量")]
        public int PageSize
        {
            get => pageSize;
            set
            {
                if (value <= 0)
                {
                    pageSize = 50;  // 默认显示50条数据
                }
                else { pageSize = value; }
            }
        }

        #endregion fields, properties

        #region methods

        private void PageSorter()
        {
            DataCount = dataSourceTable.Rows.Count;
            lblDataCount.Text = DataCount.ToString();
            PageCount = (DataCount / PageSize);
            if ((DataCount % PageSize) > 0)
            {
                PageCount++;
            }
            lblPageCount.Text = PageCount.ToString();
            CurrentPage = 1;
            lblCurrentPage.Text = CurrentPage.ToString();
            SetCtlEnabled(true);
            LoadPage();
        }

        private void LoadPage()
        {
            if (CurrentPage < 1) CurrentPage = 1;
            if (CurrentPage > PageCount) CurrentPage = pageCount;

            tempTable = dataSourceTable.Clone();

            int beginIndex, endIndex;

            if (CurrentPage == 1)
            {
                beginIndex = 0;
            }
            else { beginIndex = PageSize * (CurrentPage - 1); }
            if (CurrentPage == PageCount)
            {
                endIndex = DataCount - 1;
            }
            else { endIndex = PageSize * CurrentPage; }
            lblCurrentPage.Text = CurrentPage.ToString();
            txtTargetPage.Text = CurrentPage.ToString();
            for (int i = beginIndex; i < endIndex; i++)
            {
                DataRow row = dataSourceTable.Rows[i];
                tempTable.ImportRow(row);
            }
            dataGridViewToBind.DataSource = tempTable;
        }

        private void SetCtlEnabled(bool status)
        {
            btnFirstpage.Enabled = status;
            btnNextpage.Enabled = status;
            btnPreviouspage.Enabled = status;
            btnLastpage.Enabled = status;
            txtTargetPage.Enabled = status;
            btnSwitchPage.Enabled = status;
        }

        #endregion methods

        #region events

        private void btnFirstpage_Click(object sender, EventArgs e)
        {
            if (CurrentPage == 1)
            { return; }
            CurrentPage = 1;
            LoadPage();
        }

        private void btnPreviouspage_Click(object sender, EventArgs e)
        {
            if (CurrentPage == 1)
            { return; }
            CurrentPage--;
            LoadPage();
        }

        private void btnNextpage_Click(object sender, EventArgs e)
        {
            if (CurrentPage == PageCount)
            { return; }
            CurrentPage++;
            LoadPage();
        }

        private void btnLastpage_Click(object sender, EventArgs e)
        {
            if (CurrentPage == PageCount)
            { return; }
            CurrentPage = PageCount;
            LoadPage();
        }

        private void btnSwitchPage_Click(object sender, EventArgs e)
        {
            int num = 0;
            int.TryParse(txtTargetPage.Text.Trim(), out num);
            CurrentPage = num;
            LoadPage();
        }

        private void txtTargetPage_KeyPress(object sender, KeyPressEventArgs e)
        {
            string pattern = @"[0-9]";
            Regex regex = new Regex(pattern);
            if (!regex.IsMatch(e.KeyChar.ToString()) && !char.IsControl(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        #endregion events
    }
}

DataGridView 控件分页

客户端使用:

DataTable dataTable = new DataTable();
dataTable.Columns.Add("ID", typeof(int));
dataTable.Columns.Add("Name", typeof(string));
dataTable.Columns.Add("Age", typeof(string));
dataTable.Columns.Add("Age1", typeof(string));
								......
dataTable.Columns.Add("Age15", typeof(string));
for (int i = 1; i <= 100000; i++)
{
  DataRow newRow = dataTable.NewRow();
  newRow["ID"] = i;
  newRow["Name"] = "Name_" + i;
  newRow["Age"] = i * 1.2;
  dataTable.Rows.Add(newRow);
}
superGridView1.DataSource = dataTable;
skinDataGridView1.DataSource = dataTable;
pagerControl1.DataSource = dataTable;

DataGridView 控件分页

大致上就这个样子,还是有很大的改进空间的🌎

Demo的代码上传到GitHub了,感兴趣的友友们可以参考一下:PagerControl

还有一件事,真的很讨厌维护N年前老师傅写的项目,太痛苦了😭😭😭

参考

MSDN:

  • MSDN - Developing Custom Windows Forms Controls with the .NET Framework

  • MSDN - Develop Windows Forms controls at design time

技术博文:

  • Winform控件开发总结目录 - 白话Programing

  • C# Winform开发以及控件开发的需要注意的,被人问怕了,都是基础常识 - DSkin

  • 锋利的C# - 代码迷途

  • 浅谈Winform控件开发(一):使用GDI+美化基础窗口 - __Meow

  • C# datagridview分页功能 - 没事写个Bug - 非自定义控件

  • WinForm轻松实现自定义分页(转载)

  • WinForm下编写分页控件,实现DataGridView的分页效果 - 牛迁迁文章来源地址https://www.toymoban.com/news/detail-599838.html

到了这里,关于DataGridView 控件分页的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用双缓冲技术解决winform窗体控件卡顿(dataGridView加载数据缓慢)

    在做C/S项目中,做好的窗体出现了页面加载控件缓慢,放大、缩小窗体之后,窗体加载卡顿,以及数据渲染缓慢。 百度介绍:我们看电视时,看到的屏幕称为OSD层,也就是说,只有在OSD层上显示图像我们才能看到。现在,我需要创建一个虚拟的、看不见但是可以在上面画图(

    2024年02月02日
    浏览(30)
  • C#Winform中DataGridView控件根据鼠标左右键获取单元格值或者行列

    有多种方法可以获取单元格的值或者行列,此处选用了两种方式去获取分别用了CurrentCell方法和Rows[].Cells[]的方法去获取行列值 鼠标左键获取单独行列值 此处获取左键行列值的触发条件是表格中数据变化获取,对应DataGridView事件CellValueChanged。 用方法CurrentCell中的Value,RowIndex

    2024年02月09日
    浏览(32)
  • c# 从零到精通 读取连接数据库-并将数据填入dataGridView控件中

    c# 从零到精通 读取连接数据库-并将数据填入dataGridView控件中 using System; using System.Data; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; namespace Test01 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { SqlConnection conn

    2024年02月09日
    浏览(35)
  • c# 从零到精通 读取连接数据库-并将数据填入dataGridView控件中,并且获取所选单元格的值

    c# 从零到精通 读取连接数据库-并将数据填入dataGridView控件中,并且获取所选单元格的值 using System; using System.Data; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; namespace Test02 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } SqlConnection conn; SqlDataAdapter sd

    2024年02月09日
    浏览(32)
  • 双击dataGridView控件中的数据行,弹出另一个窗体,并将数据传递到另一个窗体中的方法。实现窗体调用,并数据传输

    //实例化学生明细的窗体 public static frmStudentDetail frmsd; //主窗体双击单元格的事件 private void dgvStudent_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)//双击单元格的事件 { //通过Serverice类中的方法得到学生类 Student objectStudent = StudentService.GetStudentInfo(Convert.ToInt32( dgvStudent.Curr

    2024年02月04日
    浏览(32)
  • 打印Winform控件实现简陋版的分页打印(C#)

    本文的代码可以从这里获取:winformDemo.rar · 张祥裕/分享的资源名称 - Gitee.com 作者的水平有限,如有错误,望指正。 为了简单起见,纸张大小,打印机等信息按照默认的来,本文的实现方案是:打印Panel中的控件信息,循环进行打印,打印完一张,把信息重新填充到对应的控

    2024年02月14日
    浏览(25)
  • 在Winform分页控件中集成保存用户列表显示字段及宽度调整设置

    在Winform的分页控件里面,我们提供了很多丰富的功能,如常规分页,中文转义、导出Excel、导出PDF等,基于DevExpress的样式的分页控件,我们在其上面做了不少封装,以便更好的使用,其中就包括集成保存用户列表显示字段及宽度调整设置。本篇随笔介绍这个实现的过程,通过

    2024年02月03日
    浏览(31)
  • MFC第二十四天 使用GDI对象画笔和画刷来开发控件(分页控件选择态的算法分析、使用CToolTipCtrl开发动静态提示)

    CMainDlg.h CMainDlg.cpp CLadderCtrl.h CLadderCtrl.cpp CMainDlg.h CMainDlg.cpp CLadderCtrl.h CLadderCtrl.cpp: 实现文件 本次只添加了与静态提示不同之处的代码 CMainDlg.h CMainDlg.cpp 设置动态文字的函数 CLadderCtrl.h CLadderCtrl.cpp MouseMove 进入任意控件都不会理你 除非回到主窗口范围内 OnSetCursor 不论在什么控

    2024年02月15日
    浏览(33)
  • C#使用DataGridView模拟绘图

    接到一个需求,绘制一个水管线的图片,这种管线可以有12种分段方法,最后将这12种分段方法合并后在一条水管线上展示,要求: ⒈支持分段的属性展示; ⒉要求每个分段都能清晰展示,分段数在0(没有分段)~100之间,水管线长度不定; 3、每个分段的属性都有值,可以更

    2024年02月16日
    浏览(31)
  • C# Winform DataGridView 数据刷新问题

    目录 一、问题 二、创建项目 三、绑定空的数据源 四、绑定有数据的数据源 五、修改绑定的数据源 六、解决数据源刷新问题 七、解决刷新数据界面闪烁 DataGridView 是比较常用的表格控件,在 DataGridView 中显示数据, 一般使用 dataGridView1.DataSource = 数据源,来绑定数据,数据

    2024年02月12日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包