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

来源:互联网 发布:基坑设计知乎 编辑:程序博客网 时间:2024/06/08 03:06

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

这是做好后的效果图,左侧是横坐标,可以任意勾选,底部是各系列,也可任意勾选

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

组别 横坐标(月份) 纵坐标(小时) 用户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循环的加载速度也是可以接受的,比反复连接数据库会快很多,尽量选择少去连接数据库,这会提高不少速度~

1 0
原创粉丝点击