DEV ChartControl绑定DataTable多系列多数据详细讲解

dev的chartcontrol控件其实是很强大的,可以根据数据库直接绑定DataSouce,也可以自己为它的每一个系列添加坐标点,即一个包含横坐标和纵坐标的SeriesPoint,这些都是可以通过这个控件自带的属性和方法解决的,难点在于控制横坐标的显示和隐藏,我找了很久没有找到控制横坐标显示隐藏的属性,迫不得已采用更改数据源也就是DataTable的办法来控制,以下就是详细过程。

DEV ChartControl绑定DataTable多系列多数据详细讲解_第1张图片

首先就是我们要用到的数据源,这里我用到的是数据库中的一个表,大致内容如下:

组别 横坐标(月份) 纵坐标(小时)
用户1 2011-05 6.38
用户2 2011-05 55.1
用户3 2011-06 22.6

很容易看出来这是进行了两次细分的,首先是组别,而后又是横坐标。

设计过程:加载数据,函数如下,第一个参数当然是我们的数据源了:

 private void LoadDataSouce(DataTable dt, Boolean isLoadTreeView)
        {
            chartControl1.Series.Clear();
            if (dt == null) return;
            //组别名
            seriesName = dt.Columns[0].ColumnName;
            //横坐标名
            abscissaName = dt.Columns[1].ColumnName;
            //纵坐标名
            valueName = dt.Columns[2].ColumnName;
            //这里主要为了对数据源进行筛选过滤,所以使用了DataView来做一个桥梁
            DataView dv = new DataView(dt);
            //这个DataTable就是我们所有的系列了
            DataTable dt_Group = dv.ToTable(true, seriesName);
            for (int i = 0; i < dt_Group.Rows.Count; i++)
            {
                Series Series1 = new Series(dt_Group.Rows[i][0].ToString(), ViewType.Bar);
                Series1.ArgumentScaleType = ScaleType.Qualitative;
                //这一句是关键,用于取出所有当前系列所对应的横坐标和纵坐标,相当于sql语句中的where子句
                DataRow[] dr = dt.Select("" + seriesName + "='" + dt_Group.Rows[i][0].ToString() + "'", abscissaName + " asc");
                Series1.Points.Clear();
                //开始加点,速度还是很快的,这里比重复连接数据库来读取DataTable会快很多
                Series1.Points.BeginUpdate();
                for (int k = 0; k < dr.Length; k++)
                {
                    if (dr[k].ItemArray[1].ToString() == "" || dr[k].ItemArray[2].ToString() == "") continue;
                    Series1.Points.Add(new SeriesPoint(dr[k].ItemArray[1], dr[k].ItemArray[2]));
                }
                Series1.Points.EndUpdate();
                chartControl1.Series.Add(Series1);
            }
            //系列名在图表上的横向位置
            chartControl1.Legend.AlignmentHorizontal = LegendAlignmentHorizontal.Center;
            //系列名在图表上的纵向位置,指定在底部
            chartControl1.Legend.AlignmentVertical = LegendAlignmentVertical.BottomOutside;
            chartControl1.Legend.Direction = LegendDirection.LeftToRight;
            //打开复选框,可以任意选择系列
            chartControl1.Legend.UseCheckBoxes = true;
            //这里开始设置XY轴
            DevExpress.XtraCharts.XYDiagram xyDiagram1 = (XYDiagram)this.chartControl1.Diagram;
            xyDiagram1.AxisX.Title.Visibility = DevExpress.Utils.DefaultBoolean.True;
            xyDiagram1.AxisX.Title.Text = abscissaName;
            xyDiagram1.AxisY.Title.Visibility = DevExpress.Utils.DefaultBoolean.True;
            xyDiagram1.AxisY.Title.Text = valueName;
            if (isLoadTreeView == true) LoadTreeView();
        }

这里加载数据源还有另外一种方法,就是不加点,直接绑定DataTable:

//这里绑定的是每一个系列的datatable,也就是说必须先把数据源过滤了再来绑定
Series1.DataSource = dt;
//这个属性必须和绑定的datatable中的列名一致
Series1.ArgumentDataMember=abscissaName;
//可以指定多个纵坐标,这里只有一个,也必须和绑定的datatable中一致
Series1.ValueDataMembers[0] = valueName;

有兴趣的话可以去试一试这两种方法,对比一下。

数据源基本上已经配置好,接下来就是加载左侧的树状控件,这个很简单,我的函数就是LoadTreeView(),这里不再贴代码。

接下来困扰很久的就是点击treeview来选择横坐标了,注册AfterCheck事件,如下:

private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            //这里的flag主要是防止在加载treeview时循环调用该事件
            if (flag == false) return;
            if (e.Node.Parent != null && e.Node.Parent.Text == "横坐标")
            {
                //这里不建议直接将dtGroup赋值给dtTemp,貌似容易出问题
                DataTable dtTemp = new DataTable();
                dtTemp = dtGroup.Copy();
                for (int i = 0; i < e.Node.Parent.Nodes.Count; i++)
                {
                    if (e.Node.Parent.Nodes[i].Checked == true) continue;
                    //将所有没选中的横坐标从缓冲DataTable里移除
                    DataRow[] dr = dtTemp.Select(abscissaName + "='" + e.Node.Parent.Nodes[i].Text + "'");
                    for (int j = 0; j < dr.Length; j++)
                    {
                        dtTemp.Rows.Remove(dr[j]);
                    }
                }
                LoadDataSouce(dtTemp, false);
            }
        }

至此基本上就已经完成所有功能了,总结的说,最重要的是利用了DataTable的select()方法来过滤移除不满足条件的行,for循环的加载速度也是可以接受的,比反复连接数据库会快很多,尽量选择少去连接数据库,这会提高不少速度~

你可能感兴趣的:(Dev控件)