如何在 WPF 中构建甘特表
本帖最后由 Richard.Ma 于 2024-10-9 11:19 编辑在当今的项目管理和调度时代,可视化的项目管理组件对于保持团队的协调一致和步入正轨至关重要。在这些组件中,甘特图是用于项目管理和跟踪的最有效的控制之一。图表以其发明者亨利·甘特 (Henry Gantt) 的名字命名,以图形方式表示项目进度。
ComponentOne 提供C1GanttView 控件,用于在 Windows 桌面应用中实现甘特图功能。此控件沿时间线可视化任务,提供项目时间线、任务持续时间、依赖关系和资源的清晰视图。它适用于 .NET Framework / .NET 6+ 中的 WinForms 和 WPF开发平台。
在本博客中,我们将使用ComponentOne WPF 套件中的 C1GanttView 控件开发甘特图 UI 。此 UI 将显示项目进度表、时间线、流程和资源信息。开发完成后,甘特图 UI 将类似于下图:https://cdn.mescius.io/umb/media/kqij11ob/gantt-chart-ui.png?rmode=max&width=691&height=389
内容摘要:
[*]WPF 甘特图主要功能
[*]在 Visual Studio 中使用 WPF Gantt View Control
[*]设置 WPF 项目以添加所需的依赖项
[*]创建GanttView UI
[*]向 C1GanttView 添加任务资源
[*]将任务添加到 C1GanttView
WPF 甘特图主要功能
[*]运行时交互: GanttView 有一个内置工具栏,使用户能够在运行时快速访问各种操作。
[*]时间标尺:GanttView 图表具有时间标尺功能,可用于显示项目的时间表。
[*]任务栏:每个任务都以水平条表示,条的长度表示任务的持续时间。这样可以轻松查看哪些任务正在进行中以及它们的预计持续时间。
[*]依赖项/前置任务:任务通常依赖于其他任务的完成。C1GanttView 图表以连接相关任务的箭头或线条直观地表示这些依赖关系,突出显示它们的顺序和关系。
[*]可定制的任务: GanttView 提供许多任务元素,允许定制任务,包括资源、前任、摘要、持续时间以及开始和结束时间。
[*] 资源分配管理:GanttView 可以显示资源在任务之间的分配方式,有助于工作量管理并确保高效的资源利用。
在 Visual Studio 中使用 WPF Gantt View Control
设置 WPF 项目以添加所需的依赖项:首先在 Visual Studio 2022 中创建一个 WPF 项目,然后按照以下步骤操作:
1.打开 Visual Studio 并选择文件->新建->项目。
2.在搜索框中搜索“WPF”,选择“ WPF应用程序”,单击“下一步”按钮。
https://cdn.mescius.io/umb/media/brhchous/new-project.png?rmode=max&width=621&height=4373.输入项目名称、项目位置和解决方案名称。然后单击“下一步”按钮。
4.从下拉菜单中选择框架(.Net 8.0 或 .Net 9.0),然后单击“创建”按钮。
5.添加必要的依赖项。在这里,我们添加 GanttView 依赖项以在我们的应用程序中显示甘特图。按照以下步骤安装 NuGet 包:
在解决方案资源管理器中,右键单击项目并选择管理 NuGet 包。
https://cdn.mescius.io/umb/media/nyunj1ng/manage-nuget-packages.png
在搜索栏中搜索“C1.Wpf.GanttView”,然后安装最新版本的 C1.WPF.GanttView NuGet 包。
https://cdn.mescius.io/umb/media/itofrqb4/nuget-package.png?rmode=max&width=706&height=198
我们现在已经建立了一个 WPF 项目并添加了所需的依赖项。
创建 WPF 甘特图视图 UI在此步骤中,我们将创建一个 GanttView UI,显示项目任务的时间线和列。按照以下步骤创建 GanttView UI:
在MainWindow.xaml文件的Window标签中添加xmlns属性:
xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml"
xmlns:GanttView="clr-namespace:C1.GanttView;assembly=C1.WPF.GanttView"
在 Xaml 中的 <Grid></Grid> 标签下添加 C1GanttView 控件。
<Grid>
<c1:C1GanttView x:Name="ganttView" StartDate="2024/09/01" ChartStartDate="2024/09/01" ChartFinishDate="2024/11/10" >
</c1:C1GanttView>
</Grid>
在C1GanttView标签下添加列,以便用特定的列初始化Gantt GridView。代码如下:
<Grid>
<c1:C1GanttView x:Name="ganttView" StartDate="2024/09/01" ChartStartDate="2024/09/01" ChartFinishDate="2024/11/10" >
<c1:C1GanttView.Columns>
<GanttView:TaskPropertyColumn Property="Name"/>
<GanttView:TaskPropertyColumn Property="Duration" />
<GanttView:TaskPropertyColumn Property="DurationUnits" />
<GanttView:TaskPropertyColumn Property="Start"/>
<GanttView:TaskPropertyColumn Property="Finish"/>
<GanttView:TaskPropertyColumn Property="ResourceNames" Visible="False"/>
</c1:C1GanttView.Columns>
</c1:C1GanttView>
</Grid>
在 MainWindow() 构造函数中处理GanttView 的Loaded事件来调整 GridView 的宽度:
public MainWindow()
{
InitializeComponent();
ganttView.Loaded+=(s, e) =>
{
//This will update the GridView Width on load
ganttView.GridWidth = 750;
};
}
GanttView 用户界面将如下所示:https://cdn.mescius.io/umb/media/pfwhv0qr/ganttview-ui.png?rmode=max&width=680&height=345
将任务资源添加到甘特图控件在上一步中,我们为 GanttView 创建了带有任务列的蓝图。现在,让我们为 GanttView 添加一些资源:<Grid>
<c1:C1GanttView x:Name="ganttView" StartDate="2024/09/01" ChartStartDate="2024/09/01" ChartFinishDate="2024/11/10" >
<c1:C1GanttView.Columns>
<GanttView:TaskPropertyColumn Property="Name"/>
<GanttView:TaskPropertyColumn Property="Duration" />
<GanttView:TaskPropertyColumn Property="DurationUnits" />
<GanttView:TaskPropertyColumn Property="Start"/>
<GanttView:TaskPropertyColumn Property="Finish"/>
<GanttView:TaskPropertyColumn Property="ResourceNames" Visible="False"/>
</c1:C1GanttView.Columns>
<c1:C1GanttView.TaskResources>
<GanttView:Resource Name="Adam Miller" Cost="200" ID="1"></GanttView:Resource>
<GanttView:Resource Name="Ruth Radelet" Cost="500" ID="2"></GanttView:Resource>
<GanttView:Resource Name="Johnny Jewel" Cost="250" ID="3"></GanttView:Resource>
<GanttView:Resource Name="Nat Walker" Cost="400" ID="4"></GanttView:Resource>
<GanttView:Resource Name="Toby Nixon" Cost="2700" ID="5"/>
<GanttView:Resource Name="Vikas Jain" Cost="880" ID="6"/>
<GanttView:Resource Name="Carole Poland" Cost="0" ID="7"/>
</c1:C1GanttView.TaskResources>
</c1:C1GanttView>
</Grid>
将任务添加到甘特图控件我们需要将任务添加到 GanttView,每个任务都有各种属性,例如 ID、名称、开始、完成等。将任务及其属性添加到 GanttView。在这里,我们在 Loaded 事件中添加了一些 GanttView 中的任务:ganttView.Loaded+=(s, e) =>
{
//This will update the GridView Width on load
ganttView.GridWidth = 750;
//Add Tasks in GanttView
ganttView.ProjectSummary= new C1.GanttView.Task() { ID=0, Name = "Project" };
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=1, Name = "Planning", OutlineParentID =0 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=2, Name = "Ananlysis", Start= new DateTime(2024, 9, 5), Finish=new DateTime(2024, 9, 14), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =1 } }, OutlineParentID=1 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=3, Name = "Project Contract", Start= new DateTime(2024, 9, 10), Finish=new DateTime(2024, 9, 17), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =2 } }, OutlineParentID=1 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=4, Name = "Design", OutlineParentID =0 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=5, Name = "Review and Mock-Ups", Start= new DateTime(2024, 9, 12), Finish=new DateTime(2024, 9, 14), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =3 } }, OutlineParentID=4 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=6, Name = "Visual Collateral", Start= new DateTime(2024, 9, 16), Finish=new DateTime(2024, 9, 17), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =3 } }, OutlineParentID=4, Predecessors = { new Predecessor() { PredecessorTaskID = 5 } } });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=7, Name = "Copywriting", Start= new DateTime(2024, 9, 18), Finish=new DateTime(2024, 9, 20), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =4 } }, OutlineParentID=4, Predecessors = { new Predecessor() { PredecessorTaskID = 6 } } });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=8, Name = "Development", OutlineParentID =0 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=9, Name = "App Model", Start= new DateTime(2024, 9, 23), Finish=new DateTime(2024, 9, 26), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =4 } }, OutlineParentID=8 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=10, Name = "Content Editing", Start= new DateTime(2024, 9, 27), Finish=new DateTime(2024, 10, 1), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =5 } }, OutlineParentID=8, Predecessors = { new Predecessor() { PredecessorTaskID = 9 } } });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=11, Name = "Coding/Structure", Start= new DateTime(2024, 10, 2), Finish=new DateTime(2024, 10, 9), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =4 } }, OutlineParentID=8, Predecessors = { new Predecessor() { PredecessorTaskID = 10 } } });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=12, Name = "Testing", Start= new DateTime(2024, 10, 10), Finish=new DateTime(2024, 10, 15), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =5 } }, OutlineParentID=8, Predecessors = { new Predecessor() { PredecessorTaskID = 11 } } });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=13, Name = "Launch", OutlineParentID =0 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=14, Name = "Review and Improve", Start= new DateTime(2024, 10, 17), Finish=new DateTime(2024, 10, 19), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =6 } }, OutlineParentID=13 });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=15, Name = "Monitor", Start= new DateTime(2024, 10, 21), Finish=new DateTime(2024, 10, 25), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =6 } }, OutlineParentID=13, Predecessors = { new Predecessor() { PredecessorTaskID = 14 } } });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=16, Name = "Finalize", Start= new DateTime(2024, 10, 26), Finish=new DateTime(2024, 10, 30), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =6 } }, OutlineParentID=13, Predecessors = { new Predecessor() { PredecessorTaskID = 15 } } });
ganttView.Tasks.Add(new C1.GanttView.Task() { ID=17, Name = "Promotion", Start= new DateTime(2024, 11, 1), Finish=new DateTime(2024, 11, 6), DurationUnits = C1.WPF.GanttView.DurationUnits.Days, ResourceRefs = { new ResourceRef() { ResourceID =7 } }, OutlineParentID=13, Predecessors = { new Predecessor() { PredecessorTaskID = 16 } } });
};
上述步骤完成了GanttView的创建,并分配了任务和资源。您可以编译并运行示例。结果如下:https://cdn.mescius.io/umb/media/kvek3jbk/run-sample.png?rmode=max&width=691&height=389
具体的示例源码,请参考下面的附件
页:
[1]