使用Scheduler控件实现生产进度监控程序
有些网友说我发表文章太慢了,没有新的原创帖不够刺激,没有看头。我想问下您们:那么多帖子看完了没有?
学会了没有?再站在我的角度想: 原创啊,自己动手写的才算原创,要独一无二,要全中文网只有框架网才有。
但是,所有的一切需要时间,特别是那些有技术含量的帖,也许数日才发表一篇!
幸好这几天写了个生产进度监控程序,要不然交不了差,哈哈!这回没二话说了吧!
好了,转入正题:
程序介绍
近阶段参与开发某生产系统,应上级要求:boss要在自己的电脑前能看到工厂的订单情况,材料需求,
生产进度等动态信息。特别指定要像xxx系统那样图形化展示(boss参观的某系统),与同事们商量后
决定用功能强大且界面美观的Scheduler控件。我们分工合作,框架部分交于我处理了。通过2天努力
框架原型出来了,不敢独享,并特别制作一些UML图配合讲解发表出来。以供大家学习讨论。
接下来讲解框架实现,因口才及表达能力有限,有些地方不能言传只可意会。
当然,大部分内容需要自己理解了!
图一 主界面
说明:列出每月CI单(订毛单)收货情况。第页可显示5~30日数据,但选择天数越多表格越小也不利用
浏览。经测试,显示5~15日的数据最佳,用不同颜色表示到货状态,用ToolTip控件显示单据详细内容,
如百分比,到货日期等信息。用户可调整单元格高度来显示完整信息,测试时仅显示2行资料,所以调整
图形元素高度为33最适宜。
图二
说明:主界面封装在ucProduceScheduler用户控件内。如新建监控窗体拖放一个ucProduceScheduler
控件,设DockStyle为Fill。然后给控件指定一个数据源对象(实现IScheduleDataSource接口)
图三 生产进度监控程序完整视图
详细设计
监控数据源接口 IScheduleDataSource
该接口用于指定数据来源,ucProduceScheduler控件操作IScheduleDataSource提供的数据。
源代码如下:
/// <summary>
/// 生产进度监控台数据源接口
/// </summary>
public interface IScheduleDataSource
{
/// <summary>
/// 数据表,原始数据
/// </summary>
DataTable DataSource { get; }
/// <summary>
/// 开始日期
/// </summary>
DateTime StartDate { get; }
/// <summary>
/// 将数据表转换成Appointment数组
/// </summary>
/// <param name="dayCount">只显示指定天数的数据</param>
/// <returns></returns>
Appointment[] ConvertAppointment(int dayCount);
/// <summary>
/// 跟据日期创建数据源
/// </summary>
IScheduleDataSource CreateDataSource(DateTime fromTime, DateTime toTime);
//原创文章,如转载请注明出处。by www.csframework.com C/S框架网
}
定义一个基类实现IScheduleDataSource接口,命名为ScheduleDataSourceBase.然后派生出n个子类,
n个子类代表n个数据来源,所以ucProduceScheduler通过控制接口实际上控制了所有数据来源。
/// 数据源基类,实现IScheduleDataSource接口
/// </summary>
public class ScheduleDataSourceBase : IScheduleDataSource
{
protected DataTable _DataSource;
protected DateTime _StartDate;
public ScheduleDataSourceBase(DataTable source, DateTime startDate)
{
_DataSource = source;
_StartDate = startDate;
}
public virtual Appointment[] ConvertAppointment(int dayCount) { return null; }
public DataTable DataSource { get { return _DataSource; } }
public DateTime StartDate { get { return _StartDate; } }
protected bool _IsGenerateFitField = false;
/// <summary>
/// 生成Schedule控件的TimeRuler时间分隔数据
/// </summary>
/// <param name="interval">分钟数:5,10,15</param>
public void FitStartDate(int interval)
{
if (_IsGenerateFitField) return;
_DataSource.Columns.Add(TScheduleData.IntervalField, typeof(DateTime));
DateTime begin = new DateTime(_StartDate.Year, _StartDate.Month, _StartDate.Day);
DateTime temp = DateTime.MinValue;
DateTime last = DateTime.MinValue;
DateTime increase = DateTime.MinValue;
foreach (DataRow row in _DataSource.Rows)
{
//取单据的开始时间
temp = DateTime.Parse(row[TScheduleData.StartTime].ToString());
if (last != temp)
{
increase = temp;
last = temp;
}
row[TScheduleData.IntervalField] = increase;
increase = increase.AddMinutes(interval);
}
_DataSource.AcceptChanges();
_IsGenerateFitField = true;
}
public virtual IScheduleDataSource CreateDataSource(DateTime fromTime, DateTime toTime) { return null; }
}
//原创文章,如转载请注明出处。by www.csframework.com C/S框架网
DevExpress.XtraScheduler.SchedulerControl 控件展示的所有元素是Appointment对象。
我们通过扩展Appointment对象来保存自定义的数据。如DataRow,ISID,DocNo等数据。
/// 自定义预约基类(业务单数据展示基类)
/// </summary>
public class ScheduleItemBase : Appointment
{
protected DataRow _DataRow;
protected string _ISID;
protected string _DocNo;
protected int _StateValue;
public ScheduleItemBase() { }
public ScheduleItemBase(DataRow row)
{
_DataRow = row;
this.ConvertToAppointment(row);
}
public DataRow DataRow { get { return _DataRow; } }
public string ISID { get { return _ISID; } }
public string DocNo { get { return _DocNo; } }
public int StateValue { get { return _StateValue; } }
private string _ToolTip = "";
/// <summary>
/// DataRow结构转换为Appointment对象
/// </summary>
/// <param name="row"></param>
public virtual void ConvertToAppointment(DataRow row)
{
_ISID = row["ISID"].ToString();
_DocNo = ConvertEx.ToString(row[TScheduleData.KeyValue]);
_StateValue = ConvertEx.ToInt(row[TScheduleData.StateValue]);
this.Start = DateTime.Parse(row[TScheduleData.IntervalField].ToString()); //用转换后的时间作为Start属性的值
this.End = this.Start;//开始与结束时间相等
this.Subject = ConvertEx.ToString(row[TScheduleData.Subject]);
this.Location = ConvertEx.ToString(row[TScheduleData.Location]);
this.LabelId = ConvertEx.ToInt(row[TScheduleData.ColorValue]);
this.StatusId = ConvertEx.ToInt(row[TScheduleData.StateValue]);
//建议DataTable返回Description字段
this.Description = ConvertEx.ToString(row[TScheduleData.Subject]); ;
}
public string ToolTip
{
get
{
if (_ToolTip == "") _ToolTip = this.GetToolTip();
return _ToolTip;
}
}
/// <summary>
/// 返回提示消息
/// </summary>
protected virtual string GetToolTip() { return ""; }
}
//原创文章,如转载请注明出处。by www.csframework.com C/S框架网
重点介绍ScheduleItemBase的ConvertToAppointment方法。
因数据来源最低层是DataTable对象,需要转换DataTable数据为Appointment[]才能在Scheduler控件内显示。该方法用于转换DataRow为Appointment对象。
另一个是FitStartDate(int interval)方法, 作用是调整DataTable数据源的StartTime字段的值,
interval参数指定分钟数。转换StartTime的数据保存在StartDateInterval字段,转换后的格式是:
(假设interval=15分钟)
2009-12-05 00:00:000
2009-12-05 00:15:000
2009-12-05 00:30:000
2009-12-05 00:45:000
2009-12-05 01:00:000
......
显示结果:
其它核心代码:
CIScheduleDataSource CI单(订毛单)数据源
该类是实现IScheduleDataSource接口的最终派生类。
/// CI单数据源
/// </summary>
public class CIScheduleDataSource : ScheduleDataSourceBase
{
public CIScheduleDataSource(DataTable source, DateTime startDate) : base(source, startDate) { }
public override Appointment[] ConvertAppointment(int dayCount)
{
Exception.Equals(_DataSource, null);
this.FitStartDate(15);//每15分钟时间线生成一条记录
//转换数据.DataTable -> Appointment[]
Appointment[] aps = new CIAppointment[_DataSource.Rows.Count];
for (int i = 0; i <= _DataSource.Rows.Count - 1; i++)
aps[i] = new CIAppointment(_DataSource.Rows[i]);
return aps;
}
public override IScheduleDataSource CreateDataSource(DateTime fromTime, DateTime toTime)
{
DataTable dt = DemoDataSource.GetData();
DateTime start = DateTime.Parse(dt.Rows[0][TScheduleData.StartTime].ToString());
IScheduleDataSource source = new CIScheduleDataSource(dt, start);
return source;
}
}
//原创文章,如转载请注明出处。by www.csframework.com C/S框架网
CI单对象
/// CI 单
/// </summary>
public class CIAppointment : ScheduleItemBase
{
public CIAppointment() { }
public CIAppointment(DataRow row) : base(row) { }
/// <summary>
/// 返回提示消息
/// </summary>
protected override string GetToolTip()
{
string html = "单号:{0}</br>日期:{1}</br>进度:{2}";
DateTime docDate = DateTime.Parse(_DataRow[TScheduleData.StartTime].ToString());
string Location = ConvertEx.ToString(_DataRow[TScheduleData.Location]);
html = string.Format(html, _DocNo, docDate, Location);
return html;
}
/// <summary>
/// 如有特殊字段,重写该方法转换Appointment对象
/// </summary>
/// <param name="row"></param>
public override void ConvertToAppointment(DataRow row)
{
base.ConvertToAppointment(row);
}
}
//原创文章,如转载请注明出处。by www.csframework.com C/S框架网
Scheduler较复杂,这里不详细讲解了! 下载附件细细研究,我还要留时间发表其它文章。
系统需求:
vs 2008
dev express 2009 9.2x
sql express 2005
Sql连接字符串在DemoDataSource的GetData方法内修改.