2018/6/4~2018/6/8 周记

一转眼一周时间已经过去,这一周的任务是做一个实时更新的窗体运用,项目的要求有如下三点:

1、界面上窗口号不能写死,要可配置的。

2、设置一个定时器,每隔10秒更新数据。

3、由于有五个窗口,所以要使用五个DataGridView控键,但是更新数据时要求只能访问一次数据库,以此来提高性能。

        这个项目逻辑很简单,可以说没有逻辑,就是去数据库取到数据然后定时更新到界面上,本来想着给个Demo的话,马上就能照着Demo写出来,但是主管说这次不给Demo,要我自己写出来,刚听的时候还有点心里没底。毕竟这个项目是要拿出去用的,所以有点慌。后来主管又说他已经做好了,这个就相当于给我练手用的,所以必须用三层来写。一听已经做完,只是拿来练手的,心理压力马上就小了好多好多。而且不懂的还可以问主管。

首先第一个,界面上窗口号不能写死,要可配置的。实现这个很简单,对比将数据库信息存放在配置文件里面,我也直接将窗口号信息直接写在配置文件里面,将数据读出来并赋值给lable就行了。实现代码如下所示:

            lblRoomName1.Text = ConfigurationManager.AppSettings["0001"];
            lblRoomName2.Text = ConfigurationManager.AppSettings["0002"];
            lblRoomName3.Text = ConfigurationManager.AppSettings["0003"];
            lblRoomName4.Text = ConfigurationManager.AppSettings["0004"];
            lblRoomName5.Text = ConfigurationManager.AppSettings["0005"];
View Code

        后面主管说要我通过数据库表里的数据将值赋值给lable,虽然取到需要的表,表里面的数据也有,但是不知道如何将表数据准确赋值给lable,主管实际操作一波,使用DataView来实现,因为DataView里面有可以筛选表数据的方法RowFilter(),DataView就是视图的意思,可以虚拟出一张表并获取真实表的数据,和SQL里面视图一样的道理,对DataView操作就是对表进行操作。代码如下:

//通过读取数据库数据更新科室名称
            DataTable dt = bllXtRoom.GetList();

            //创建一个视图,虚拟表数据
            DataView dv = dt.DefaultView;

            //通过视图筛选符合条件的数据
            dv.RowFilter = "RoomCode ='001' ";
            //赋值
            lblRoomName1.Text = dv[0][1].ToString();

            dv.RowFilter = "RoomCode ='002' ";
            lblRoomName2.Text = dv[0][1].ToString();
            dv.RowFilter = "RoomCode ='003' ";
            lblRoomName3.Text = dv[0][1].ToString();
            dv.RowFilter = "RoomCode ='004' ";
            lblRoomName4.Text = dv[0][1].ToString();
            dv.RowFilter = "RoomCode ='005' ";
            lblRoomName5.Text = dv[0][1].ToString();
View Code

        将表数据根据条件分别填入五个DataGridView里面。我的做法就是写五条数据库语言,分别查出所需要的数据,然后分别填入DataGridView里面(后面要一次性跟新整个界面数据时,这样取数据是不行的!每跟新一次数据就要访问五次数据库!)数据填入DataGriView里面并不美观,其中最重要的是数据在DataGridView里面自适应列宽。这样数据看着才会比较整齐!因为背景图片已经给出来了,所以每个DataGridView的大小已经定下来了。DataGridView里面每一列的宽度就要自适应,不然很影响美观的。自适应代码如下所示:

 public void SetWidth(DataGridView data)
        {
            int width = 0;
       
            //对于DataGridView的每一个列都调整
            for (int i = 0; i < data.Columns.Count; i++)
            {
                //将每一列都调整为自动适应模式
                data.AutoResizeColumn(i, DataGridViewAutoSizeColumnMode.AllCells);
                //记录整个DataGridView的宽度
                width += data.Columns[i].Width;
            }
            //判断调整后的宽度与原来设定的宽度的关系,如果是调整后的宽度大于原来设定的宽度,
            //则将DataGridView的列自动调整模式设置为显示的列即可,
            //如果是小于原来设定的宽度,将模式改为填充。
            if (width > data.Size.Width)
            {
                data.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
            }
            else
            {
                data.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            }
            //冻结某列 从左开始 0,1,2
            data.Columns[1].Frozen = true;
        }
View Code

        数据填入DataGridView后就是定时更新的问题了,定时更新有两个方法,一个是写一个线程,通过线程定时来定时访问数据库实现更新数据,第二个是使用定时器,写一个定时器来定时执行。简单线程很简单,只需要实例化一个Thread,然后调star()方法。代码如下:

 private void UpData()
        {
            while (true)
            {
                //运行时间
                Thread.Sleep(10000);
                DataTable dt = bllQueueList.GetTable();
                // dataGridView4.DataSource = dt4;
                SetDT(dt);
                //qubiaotou(dataGridView4);
                //SetWidth(dataGridView4);
              
            }
        }

//使用线程调用方法
//在Load方法里面执行
            Thread th = new Thread(UpData);
            th.Start();
View Code

定时器的话也很简单,拉一个定时器控键,设置Enabled=true,Interval=1000;//执行时间间隔,单位为毫秒

            //方法二:使用定时器
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Enabled = true;
            timer.Interval = 10000;//执行间隔时间,单位为毫秒  
            timer.Start();
            timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer1_Elapsed);


        private void Timer1_Elapsed(object sender, ElapsedEventArgs e)
        {
            DataTable dt = bllQueueList.GetTable();
            
            SetDT(dt);
            
        }
View Code

但是这样写出来的定时器还是会报错,错误信息是“线程间操作无效: 从不是创建控件“”的线程访问它”。解决方法是通过写一个委托来执行

       
 private delegate void SetDtCallback(DataTable dt);
 private void SetDT(DataTable dt)
        {
            // InvokeRequired需要比较调用线程ID和创建线程ID
            // 如果它们不相同则返回true
            if (this.InvokeRequired)
            {
                SetDtCallback d = new SetDtCallback(SetDT);
                this.Invoke(d, new object[] { dt });
            }
            else
            {
                // dataGridView4.DataSource = dt;
                ShowData();
            }
        }
View Code

虽然功能实现了,但是还是不懂什么意思。。

将一个表里面数据通过条件分成多个表:

DataTable dt = bllQueueList.GetTable();
            DataView dataview = dt.DefaultView;


            DataTable dt1 = new DataTable();
            //通过视图筛选符合条件的数据
            dataview.RowFilter = "Window='1001'";
            //创建一个新的表,该表只显示"Queueno","Name"这两个列的值并把表数据赋值给表dtTemporary,
            //true:不显示相同的数据,false:显示全部数据
            dt1 = dataview.ToTable(true, "Queueno", "Name");
            dataGridView1.DataSource = dt1;
            qubiaotou(dataGridView1);
            SetWidth(dataGridView1);
View Code

还有一些细节方面的问题。。用户体验真的很重要!!!

操作数据库时,往表里添加数据时报将截断字符串或二进制数据。的错误。原因是数据的长度不符合才造成的。只要把数据长度增加就行了!!

原文地址:https://www.cnblogs.com/cc1120/p/9148961.html