Aimin Han

SharePoint Server、Office、Silverlight、Flash、GIS、AVEVA NET & solutions 培训 咨询 设计
posts - 39, comments - 180, trackbacks - 2, articles - 2
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

2012年2月8日

摘要: 在历次课程中,无论是之前的SharePoint版本,还是现在的SharePoint 2010,管理课程的培训学员都经常提出一个问题:如何在SharePoint中配置“单据基本信息”和“单据明细条目”组合显示的页面?且保持单据和单据条目一直的权限控制。 SharePoint 2010 中提供了文档集的内容类型,在Server版本中,可以用来处理文档库中的“文档与文件”的问题。但是对列表而言,无论是Foundation还是Server都没有出箱即用的内容类型。 本文介绍的示例是一个简单的合同管理的案例,合同有“基本信息”及“附属的合同文件”,附属文件类型比较多,如谈判记录、合同正文、技术附件等等。阅读全文

posted @ 2012-02-08 11:18 aimin 阅读(853) 评论(0) 编辑

2012年1月31日

新的服务应用程序架构是一种可扩展的中间层应用程序,可以为第三方应用程序或者服务提供数据或某种专业计算能力。新的服务应用程序架构能够被服务器场中不同服务器所共享,具备一定的负载均衡的能力,该负载均衡可自定义。

全新的服务模型将更加灵活

服务将不再依赖于 SSP,而是相对独立

Web 应用程序拥有更加宽泛的服务选择余地

可对高能耗的服务实现更优化的负载平衡

既可依附于单独的服务器场,也可在多个服务器场之间共享

所有服务器场均可专门用于服务托管

用于超高能耗型服务的成本投入可控,例如Web 分析服务、商业智能、搜索服务、Office Web等等。

 

以上讨论过于直板,为了建立更加直观的认识,我们从一个实际案例开始吧。

故事发生在某大型能源行业国有制造企业,该企业承担了国内外众多大型工厂、工程的设计和施工项目。它已经采购了SharePoint 2007,将为它的市场部、开发部、设计部提供门户网站、项目管理、产品数据管理的解决方案。三个部门的需求和业务各有特点,又前后相继,具体如下:

1、市场部

市场部包括项目的立项申请、以及项目执行过程中的保函、佣金、签约资料、信函等文档管理和成本测算管理。每个项目产生约数十上百兆的文档。

2、开发部

开发部承担报价设计、合同设计、以及交底文档管理,合同设计过程需要进行简单的管理。每个项目产生数百兆的文档。

3、设计部

设计部承担企业所有在建项目的初步设计、详细设计、完工设计等工作,要求对设计过程中图纸目录、设计计划、设计师任务、设计工时、设计图档、设计更改、图纸晒发进行有效管控。

系统将根据设计计划向任务负责人及时派发任务,提醒设校审人员在线执行校审工作,任务完成后,系统会自动生成工时单,要求设计部人员填写相应任务所耗用的工时,由专业主管在线审核。设计部每年承担的并行项目约有十余个,每个项目在完成后,产生约20-50G的各类文档:Office、CAD、各种三维模型等等。这些文档最终会形成一个可交付的结构化的项目成果库。

 

考虑到本系统承担了大量的数据存储和计算工作,因此设计院购买了3台8核16G的IBM 服务器,以及统一备份管理的高速磁盘阵列。然后,组织人员使用SharePoint 2007 实施了以上解决方案,解决方案中包含了大量自定义的工作流活动、事件处理、Web部件、应用程序页面。

服务器规划:一台SQL Server 报表服务器、一台作为应用服务器、一台前端服务器、数据库服务器使用了企业的统一SQL Server 集群。

网站规划:

case1

 

本系统上线不久,就遭遇了用户较为强烈的不满,尤其是市场部和开发部,由于这两个部门的应用只是简单的文档管理和较少的工作流管理,他们反映新上线的系统还不如之前一家小公司实施的文档管理系统响应速度快,这不合常理。

通过上面的网站规划,显而易见,且不论服务器组合是否有优化空间,网站规划逻辑本身就很有问题:所有门户和项目网站都放在同一个网站集中。

为什么说这是一个问题呢?我们可以通过SharePoint的几个基础概念来弄懂这个问题所在。

1、服务器场

将多台物理服务器组合成一个硬件资源池,从而实现单台服务器所不具备的处理能力。

2、Web应用程序

对硬件资源池的计算和存储虚拟化,任何系统都离不开两个方面:计算(CPU和内存)、存储(磁盘)。SharePoint Web应用程序使用IIS来发布,使用W3WP的一个进程实例,内存上限一般设定为800M – 1G ; 它使用SQL Server来进行数据存储。

可以回想一下SharePoint  ”管理中心”中, Web应用程序的创建过程,指定一个应用程序池名称,指定一个数据库名称(当然,一个Web应用程序可以包含N个内容数据库,此处指的是创建的第一个数据库名称,一般名称为WSS_Content_XXX),实际上可以认为是对计算资源和存储资源的分配。

小结一下:一个Web应用程序只能有一个应用程序池(计算资源,有内存上限,尤其32位系统)和多个内容数据库。

3、网站集

网站集是一堆面向具体业务应用的网站的集合。如果说Web应用程序还是对资源的分配,与具体企业业务没有具体关系的话,那么网站集则是从Web应用程序分配的资源里面分出一部分,服务于某个具体业务需求。网站集在创建的时候,会默认创建一个顶级网站,以衍生出一些列的子网站,算得上是所有网站的父亲、祖父、曾祖父……

一个网站集只能存储于一个内容数据库中。 但一个内容数据库可以存储多个网站集的内容。一个网站集只能属于一个Web应用程序,也就只能够使用当前Web应用程序对应的单个计算资源(一个W3WP,不超过1G的内存使用上限)。

4、网站

网站集中的一个具体应用的示例。

 

我们通过以上的介绍来分析一下该企业网站规划的问题所在。

首先,由于使用的是单个网站集存储所有数据,就意味着所有数据都必须存储在一个SQL Server数据库之中。该企业设计部以10个年并行项目计算,10 X 20G = 200G。每年该数据库至少多出200G的数据。而SharePoint 2007 推荐的单库大小是80G,不超过 200G。实际上很多项目在完工后,都处于只读状态,但却不得不参与数据库的查询分析,影响了数据库的性能。

其次,由于设计部的功能使用了大量的计算资源,如原始CAD dwg图纸的在线转换可视化,产品结构基线分析等等。使得共用同一“计算资源”的市场部和开发部不得不忍受着资源被抢占的痛苦。

 

明白了问题所在,参考以上的几个基础概念,在SharePoint 2007下,我们可以将设计部放置在单独的Web应用程序中,将市场部和开发部放置于另一个Web应用程序中,从而将双方的计算资源独立。此外,使用网站集来管理每一个项目,从而确保每个内容数据库中容纳不超过2个项目网站集。似乎一切都开始正常了。

但是也存在一些问题,譬如,由于存在两个Web应用程序,在部门网站切换时,需要再次认证;在调用另一个Web应用程序数据时,需要额外的认证和设置等等。

 

在SharePoint2010 中,这些可以进一步优化,譬如我们看到的Office Web App服务,就类似于CAD文档在线可视化的服务,在新的服务应用程序架构中,这种高能耗的服务被独立出来了,可以使用单台或多台服务器,甚至一个独立的服务器场为该运算进行服务。同样,对于一些具备全局特点的数据,也可以通过服务应用程序来提供。

 

但是为了适应Sharepoint 2010的服务架构,我们提供一个A+B的加法运算服务,也需要编写大量的代码,使它能够通过Powershell创建、在管理中心被设置,被Web应用程序关联调用等等。所以,它是一把牛刀,非必要场合不要用它,毕竟开发者都是比较懒的。

posted @ 2012-01-31 12:01 aimin 阅读(1148) 评论(9) 编辑

2012年1月29日

如果说TimeLine,GanttPanel,TreeGrid是甘特图控件的三个核心部件,那么Gantt则是这三个部件之间行为和数据的协调者,Gantt统一了这三个部件的接口,提供了更简洁的开发能力。

 

架构提要:

功能:

ganttfunctions

设计:

 

design

在*.Gantt.Core 程序集中,可以发现大量的以Layout和Descriptor作为结尾的命名类,这些类构件了GanttPanel和TimeLine的计算模型和数据模型。

TimeLineViewer和TaskEntryViewer分别作为TimeLine和GanttPanel的视图层。Viewer类会调用Renderer进行渲染。

 

1. 语法

1.1. XAML

2. 备注

2.1. 设置数据源

甘特图控件目前仅支持特定的数据源格式: ObservableCollection<ITaskDescriptor>。其中ITaskDescriptor是单任务信息的数据接口,详细信息参考Class Library中内容。

因此,面对来自不同类型数据源的任务信息,开发者必须编写解析类或方法,将XML,JSON等类型的数据转化为甘特图指定的数据源类型。

除初始化设定数据源外,甘特图控件允许分步加载数据,这是通过OnRequestData事件响应来实现的。

激发OnRequestData事件的条件时,展开当前任务,任务的ITaskDescriptor.EnableExpand=true,但ITaskDescriptor.Children.Count = 0;

示例代码如下:

1) 事件处理函数逻辑

   1: ObservableCollection<ITaskDescriptor> Gantt_OnRequestData(object sender, V2TEK.Silverlight.Charts.TreeGridHelper.RequestDataArgs args)
   2: {
   3:     return GetSimWCFData();
   4: }
   5:  
   6: public ObservableCollection<ITaskDescriptor> GetSimWCFData()
   7: {
   8:     return new ObservableCollection<ITaskDescriptor>
   9:     {

10: new SimpleTaskDescriptor{ TaskName="--------Sub Task 1", StartDate= DateTime.Now.AddMonths(4), EndDate=DateTime.Now.AddMonths(5), PercentComplete=25f,

TimeBaseLine=new SimpleTimeImpl{ StartDate=DateTime.Now.AddMonths(1), EndDate=DateTime.Now.AddMonths(10)} },

  11:         new SimpleTaskDescriptor{ TaskName="--------Sub Task 2", StartDate= DateTime.Now.AddMonths(2), EndDate=DateTime.Now.AddMonths(3), PercentComplete=50f },
  12:         new SimpleTaskDescriptor{ TaskName="--------Sub Task 3", StartDate= DateTime.Now.AddMonths(3), EndDate=DateTime.Now.AddMonths(5), PercentComplete=75f },
  13:         new SimpleTaskDescriptor{ TaskName="--------Sub Task 4", StartDate= DateTime.Now.AddMonths(5), EndDate=DateTime.Now.AddMonths(10),  PercentComplete=100f }
  14:     };
  15: }

2.2. 导航

导航指从指定任务的开始时间,或指定时间开始绘制甘特图,免于使用滚动条搜寻。

1) 导航到指定任务

NavigateTo(ITaskDescriptor task)

2) 导航到选中任务

NavigateToSeleteItem()

3) 导航到当前时间

NavigateToCurrentDate()

4) 导航到指定时间

NavigateToDate(DateTime date)

2.3. 放大/缩小

根据TimeLine中定义的时间轴分级缩放机制逐级放大或缩小,提供了三个接口:

1) ZoomOut()

放大到下一级

2) ZoomIn()

缩小至上一级

3) ZoomToIndex(int index)

缩放至指定级别, Index即Dictionary<IDateTimeDescriptor, int>的索引。

此外,Gantt允许设置TimeLineSummaryDescriptors和TimeLineDetailDescriptors属性值。

1) TimeLineSummaryDescriptors是上层时间轴的缩放分级定义。

2) TimeLineDetailDescriptors是下层时间轴的缩放分级定义。

2.4. 布局

除了通过以上接口更新Gantt的布局外,还可以通过下面的接口实现更为细致的布局更新。

Gantt提供了诸如XPosition,YPosition,GanttViewPortHeight,GanttViewPortWidth等布局的设定接口。在修改了这些布局属性值后,须调用Update方法。当然,也可以分别调用GanttPanel.Update(), TreeGrid.Update, TimeLine.Update, 前提是开发者能够确定需要更新那个子控件的布局。

You need to install Microsoft Silverlight to view this content. Get Silverlight!
Get Microsoft Silverlight


posted @ 2012-01-29 14:55 aimin 阅读(430) 评论(5) 编辑

1. 语法

1.1. XAML

2. 备注

当前版本的TreeGrid仅可以使用甘特图控件指定数据源格式。如需支持其他类型数据源,需要重新实现AbstractExpander和AbstractTreeGridLayout。

2.1. 定义Expander样式

通过自定义AbstractExpander的集成类,并设置TreeGrid.ExpanderProvider,可实现Expander的自定义,从而更换逻辑或样式。

自定义类的实现可参考默认提供的Expander类:SimpleTaskExpander

 

TreeGrid是扩展Silverlight自身提供的DataGrid实现的,关键是自定义了新的Column类型,此Column在每一行的单元格中添加了一个按钮控件,根据任务的层级缩进,并在用户单击时,发起一个“展开/折叠”事件,事件EventArgs中包含行所对应的任务Item数据。

代码如下:

   1: namespace V2TEK.Silverlight.Charts.TreeGridHelper
   2: {
   3:     /// <summary>
   4:     /// 包含一个默认的Expander,继承自AbstractExpander。
   5:     /// 如有必要,可以通过继承AbstractExpander,复写Expander,并设置ExpanderProvider。
   6:     /// </summary>
   7:     public class TreeGridExpanderColumn : DataGridTextColumn
   8:     {
   9:         public TreeGridExpanderColumn()
  10:         {
  11:         }
  12:  
  13:         private AbstractExpander CreateExpander()
  14:         {
  15:             return Activator.CreateInstance(ExpanderProvider) as AbstractExpander;        
  16:         }
  17:  
  18:         public Type ExpanderProvider
  19:         {
  20:             get;
  21:             set;
  22:         }
  23:  
  24:         protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
  25:         {
  26:             StackPanel panel = GeneratePanel(dataItem);
  27:             panel.Children.Add(base.GenerateEditingElement(cell, dataItem));
  28:             return panel;
  29:         }
  30:  
  31:         protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
  32:         {
  33:             StackPanel panel = GeneratePanel(dataItem);
  34:             panel.Children.Add(base.GenerateElement(cell, dataItem));
  35:             return panel;
  36:         }
  37:  
  38:         protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
  39:         {
  40:             TextBox ee = editingElement as TextBox;
  41:             if (ee == null)
  42:             {
  43:                 return string.Empty;
  44:             }
  45:             string text = ee.Text;
  46:             int length = text.Length;
  47:             KeyEventArgs args = editingEventArgs as KeyEventArgs;
  48:             if ((args != null) && (args.Key == Key.F2))
  49:             {
  50:                 ee.Select(length, length);
  51:                 return text;
  52:             }
  53:             ee.Select(0, length);
  54:  
  55:             return base.PrepareCellForEdit(editingElement, editingEventArgs);
  56:         }
  57:  
  58:         public AbstractExpander GetExpander(DataGridRow row)
  59:         {
  60:             StackPanel panel = (StackPanel)this.GetCellContent(row);
  61:             AbstractExpander expander = panel.Children[0] as AbstractExpander;
  62:             expander.Data = row.DataContext;
  63:             return expander;
  64:         }
  65:  
  66:         private StackPanel GeneratePanel(object dataItem)
  67:         {
  68:             StackPanel panel = new StackPanel();
  69:             panel.Orientation = Orientation.Horizontal;
  70:             panel.Children.Add(GenerateExpander(dataItem));
  71:             return panel;
  72:         }
  73:  
  74:         private AbstractExpander GenerateExpander(object dataItem)
  75:         {
  76:             AbstractExpander expander = CreateExpander();
  77:             expander.Data = dataItem;
  78:             expander.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(expander_PropertyChanged);
  79:             return expander;
  80:         }
  81:  
  82:         void expander_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
  83:         {
  84:             if (e.PropertyName == AbstractExpander.DATA_PROPERTY)
  85:                 (sender as AbstractExpander).Update();
  86:         }
  87:     }
  88: }

posted @ 2012-01-29 14:47 aimin 阅读(1244) 评论(0) 编辑

1. 语法

1.1. XAML

2. 备注

2.1. 布局计算

GanttPanel与TimeLine的计算方法类似,仅计算ViewPort范围内需要绘制的任务项,但是多了一个参数YPosition。YPostion是纵向坐标上的位置。

纵向坐标轴:当前已展开的所有任务项中最顶端的YPosition=0,依次递增数为1。

GanttPanel.TaskEntryLayout.Rows属性枚举了所有展开的任务项,而GanttPanel.TaskEntryLayout.Items仅仅枚举了当前需要绘制的任务项。

同时GanttPanel.TaskEntryLayout布局计算,允许每行Row中有多个Items。这种情况一般应用在资源任务图表上,即查看每个资源所参加或负责的任务项。要实现资源任务图表,必须继承继承自AbstractTaskEntryLayout类,可参考SimpleTaskEntryLayout的实现,重新构造AbstractTaskEntryLayout.Rows成员项。同时,必须制定GanttPanel. TaskEntryLayoutProvider的值为自定义的Layout实现类。

2.2. 渲染

GanttPanel允许自定义渲染甘特图横向条目,要求实现ITaskEntryRenderer接口或继承自AbstractTaskEntryRenderer。在3.2.3 Walkthrough,将会给出一个通过这种方法创建关键路径显示的方式。

3. 示例

posted @ 2012-01-29 14:42 aimin 阅读(1062) 评论(0) 编辑

2012年1月20日

1. 语法

1.1. XAML

2. 备注

2.1. 布局计算

TimeLine作为时间轴(横向坐标),其精度为毫秒。原点为StartDate,相对于原点的位置为某一时间点减去开始时间所得时间的毫秒数,即XPosition。

TimeLine布局计算继承自ILayout接口,主要依赖于XPosition,ViewPortWidth,ViewPortHeight属性。

出于性能考虑,TimeLine仅仅计算出当前ViewPortWidth和ViewPortHeight范围内的所需的单元格(表示时间段的方格)。

2.2. 渲染

TimeLine允许自定义Renderer的风格,自定义的Renderer类必须继承自ITimeLineEntryRenderer接口。可参考SimpleTimeLineEntryRenderer的实现。并指定TimeLine.ItemRendererProvider的值为自定义的Renderer类。

2.3. 放大/缩小

时间轴控件允许自定义放大缩小的层级,从而变换“年/季度”,“年/月”,“月/日”等不同样式。

设定放大缩小层级,必须了解Dictionary<IDateTimeDescriptor, int>和最小MinDateTimeRangeWidth 的定义。

1) Dictionary<IDateTimeDescriptor, int>

IDateTimeDescriptor表示TimeLine上同一时间轴上每个方块显示的时间范围,即一个单元时间范围,如下面的代码表示2季度:

   1:  
   2: new SimpleDateTimeDescriptor(2, DateTimeType.Quarter)

Dictionary包含N个IDateTimeDescriptor,依次排列。即排列中枚举了N级单元时间范围。

2) MinDateTimeRangeWidth

MinDateTimeRangeWidth 表示绘制IDateTimeDescriptor时间范围的最小长度。如MinDateTimeRangeWidth = 80d; 则表示80像素表示2个季度时间的长度。

3) 放大原理

举一个简单的例子,设定如下:

   1:  
   2: ITaskDescriptor t = new SimpleTaskDescriptor{StartDate=2010/1/1, 
   3: EndDate=2010/4/1}
   4: MinDateTimeRangeWidth = 80d
   5: new SimpleDateTimeDescriptor(1, DateTimeType.Quarter)
   6: new SimpleDateTimeDescriptor(1, DateTimeType.Year)

上面定义时间开始与2010年1月1日,跨度为1个季度的任务,并定义了两级单元时间范围,此外,还定义单元时间范围在屏幕上绘制的长度下限为80像素。

当甘特图此任务条以>=80像素显示时,TimeLine上单元格显示为”X季度”。当任务以<80像素显示时,时间轴上单元格显示为”XX年”。

此外,还需注意Dictionary<IDateTimeDescriptor, int>类型中标红的int类型,此类型参数表示”跳针”,用于TimeLine的多层时间轴,譬如下图表示两层时间轴:

timeline1

显然,每一层时间轴有不同的缩放机制,而每一种放大机制都对应了一个Dictionary<IDateTimeDescriptor, int>类型的实例。从而形成”年/季度”,“年/月”等结构。

通过下面的例子,说明如何”跳针”, DefaultDateTimeRangeDescriptor是下层时间轴的缩放机制,DefaultDateTimeRangeDescriptor2是上层时间轴的缩放机制,上层时间轴使用了跳针:

   1: public static Dictionary<IDateTimeDescriptor, int> DefaultDateTimeRangeDescriptor
   2:         {
   3:             get
   4:             {
   5:                 if (_defaultDateTimeRangeDescriptor == null)
   6:                 {
   7:                     _defaultDateTimeRangeDescriptor = new Dictionary<IDateTimeDescriptor, int>();
   8:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(1, DateTimeType.Minute), 0);
   9:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(5, DateTimeType.Minute), 0);
  10:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(10, DateTimeType.Minute), 0);
  11:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(15, DateTimeType.Minute), 0);
  12:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(30, DateTimeType.Minute), 0);
  13:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(1, DateTimeType.Hour), 0);
  14:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(2, DateTimeType.Hour), 0);
  15:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(6, DateTimeType.Hour), 0);
  16:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(12, DateTimeType.Hour), 0);
  17:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(1, DateTimeType.WeekDay), 0);
  18:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(2, DateTimeType.Day), 0);
  19:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(4, DateTimeType.Day), 0);
  20:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(7, DateTimeType.Day), 0);
  21:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(1, DateTimeType.Month), 0);
  22:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(1, DateTimeType.Quarter), 0);
  23:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(2, DateTimeType.Quarter), 0);
  24:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(1, DateTimeType.Year), 0);
  25:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(2, DateTimeType.Year), 0);
  26:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(5, DateTimeType.Year), 0);
  27:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(10, DateTimeType.Year), 0);
  28:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(20, DateTimeType.Year), 0);
  29:                     _defaultDateTimeRangeDescriptor.Add(new SimpleDateTimeDescriptor(50, DateTimeType.Year), 0);
  30:                 }
  31:                 return _defaultDateTimeRangeDescriptor;
  32:             }
  33:         }
  34:  
  35:         public static Dictionary<IDateTimeDescriptor, int> DefaultDateTimeRangeDescriptor2
  36:         {
  37:             get
  38:             {
  39:                 if (_defaultDateTimeRangeDescriptor2 == null)
  40:                 {
  41:                     _defaultDateTimeRangeDescriptor2 = new Dictionary<IDateTimeDescriptor, int>();
  42:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(1, DateTimeType.Minute), 1); //-------0
  43:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(5, DateTimeType.Minute), 1);//-------1
  44:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(10, DateTimeType.Minute), 3);//-------2
  45:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(15, DateTimeType.Minute), 2);//-------3
  46:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(30, DateTimeType.Minute), 1);//-------4
  47:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(1, DateTimeType.Hour), 2);//-------5
  48:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(2, DateTimeType.Hour), 1);//-------6
  49:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(6, DateTimeType.Hour), 2);//-------7
  50:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(12, DateTimeType.Hour), 1);//-------8
  51:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(1, DateTimeType.Day), 3);//-------9
  52:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(2, DateTimeType.Day), 3);//-------10
  53:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(4, DateTimeType.Day), 2);//-------11
  54:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(1, DateTimeType.Week), 1);//-------12
  55:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(1, DateTimeType.Month), 1);//-------14
  56:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(1, DateTimeType.Quarter), 2);//-------15
  57:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(2, DateTimeType.Quarter), 1);//-------16
  58:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(1, DateTimeType.Year), 1);//-------18
  59:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(2, DateTimeType.Year), 1);//-------19
  60:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(5, DateTimeType.Year), 1);//-------20
  61:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(10, DateTimeType.Year), 1);//-------21
  62:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(20, DateTimeType.Year), 1);//-------22
  63:                     _defaultDateTimeRangeDescriptor2.Add(new SimpleDateTimeDescriptor2(50, DateTimeType.Year), 0);//-------22
  64:                 }
  65:                 return _defaultDateTimeRangeDescriptor2;
  66:             }
  67:         }

DeafultDateTimeDescriptor2中第一行Int = 1,意思是,如果当前时间轴上放大至:80像素/1分钟的话,那么直接跳到下一个,用400像素的单元格表示5分钟。

posted @ 2012-01-20 16:15 aimin 阅读(1260) 评论(3) 编辑

2012年1月19日

源码还在整理中,最迟在年后1月底2月初发布,项目名称初定为BestGantt,地址:http://bestgantt.codeplex.com/

 

该部分包括如下主题:

1) 甘特图控件是什么

2) 客户系统需求

3) 开发系统需求

1.1 什么是甘特图控件

甘特图是计划管理进度分析常用的工具之一。典型的甘特图由两个维度组成:纵向表示任务,横向时间轴表示任务进度。

本文档所表述的甘特图控件不仅可以展示出典型的甘特图样式,也可以通过二次开发显示为资源任务分配图,关键路径图。

1) 资源任务分配:纵轴表示资源列,横向时间轴表示每个资源所拥有的一个或多个分配任务。

2) 关键路径图:在典型甘特图上,将处于关键路径的任务用特定的颜色显示。

Note: 目前版本的甘特图不支持网络图,即以有向线段表示任务的前置关系。但预留了接口,可以通过二次开发实现,目前部分PDM项目已实现,通过对这些项目代码的重构,后续版本会默认支持网络图,从而减少二次开发的工作量。

taskview

resourceview

1.2 客户系统配置

IE 6以上版本 或 Firefox 2.0 以上版本

Silverlight 3, 4

1.3 开发者系统配置

控件最初使用Silverlight 3开发,因此代码支持 Silverlight 3运行时,如有需要请自行编译

开发系统软件配置需求如下

IE 6 Firefox 2.0……… 以上版本

Silverlight 3, 4 for developer

Visual Studio 2008, 2010

Microsoft Expression 3, 4

 

下一节将介绍甘特图控件及其三个主要的子控件的用法和开发原理,通过组合使用这些控件,可以开发出高效实用的甘特图应用程序。

三个子控件分别是:TimeLine, Gantt Panel, Tree Grid。

TimeLine: 时间轴,可以定义不同的缩放层级,包括年/季度,年/月,季度/月,月/日,周/日,日/时,时/分等。

Gantt Panel: 甘特图( 横道图 )显示区域,根据任务的起止时间显示柱状图形。

Tree Grid: 扩展自Silverlight DataGrid,继承了DataGrid大部分特性,并增加了显示层级化数据的能力。

guid1

posted @ 2012-01-19 15:05 aimin 阅读(1577) 评论(2) 编辑

2011年7月25日

摘要: 环境:SharePoint Fundation 2010, Silverlight 4演示地址:workspacer intro and workflow(高质量,速度较慢)workspacer intro and workflow(中等质量,速度较快)YES OA Road Map 1.0Workspacer 1.0 功能单据管理 流程管理 文档共享 即时通讯 邮箱集成 短信集成Workspacer 1.1 功能+离线工作,在线同步Workspacer 1.2 功能+图形化工作流管理 流程流转节点高亮Workspacer 2.0 功能+项目管理集成:甘特图 工时单 周/月计划阅读全文

posted @ 2011-07-25 09:46 aimin 阅读(624) 评论(1) 编辑

2010年6月23日

摘要: 二次开发的代码很简单:Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1Gantt.StartDate=DateTime.Now;2Gantt.EndDate=DateTime.Now.AddMonths(20);3Gantt.ContentWidth=1800d;4Gantt.XPosition=0;5Gantt.DataSource=GetTasks();6Gantt.OnRequestData+=newRequestDataEventH阅读全文

posted @ 2010-06-23 09:50 aimin 阅读(1088) 评论(0) 编辑

2010年6月10日

摘要: 在许多与业务紧密相关的IT项目中,进行as - is 和 to-be分析后,可以在业务层次的对象建模。在传统的开发模式中,最终会映射为关系数据库的数据表关系表和抽象的逻辑层;而在基于类似SharePoint这种对象型数据库,实施的项目时,由于它已经在关系型数据库中进行了进一步的基于对象的架构,所以我们只需要进行简单的转化和抽象,就可以直接对业务层次的对象进行系统建模。阅读全文

posted @ 2010-06-10 13:17 aimin 阅读(1550) 评论(0) 编辑