50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

使用 shieldUI Chart 控件在 ASP.NET 和 MVC 应用程序中创建一个销售仪表板

  • 2013-12-11
  • 本文字数:7500 字

    阅读完需:约 25 分钟

本文中,我们将处理一个常见的数据可视化任务,即创建一个销售仪表板(dashboard)。在商业演示中经常会使用销售仪表板来展现某个商业流程或商业目标的关键绩效指标,而完成这样一个演示的关键不仅在于对数据进行良好的可视化展示,还要有赏心悦目的外观。为了完成这一任务,我会使用相关的图表组件,它提供了全部的所需功能。这个示例中将使用 ShieldUI 中的图表组件,这一系列产品可以从网站的免费下载。

完成后的展示请见下图:

(点击图像放大)

本示例将使用ASP.NET 与MVC 两种方式讲解。

使用代码

ASP.NET 版本

我首先建立一个 Visual Studio 的 web 项目,这个 web 应用包含一个单独的.aspx 文件,其中包含了相关的控件。第二步则是将图表组件所在的.dll 文件加入当前项目:

将组件所在的.dll 文件加入项目之后,我们还需要在项目中引用它。可以直接在.aspx 页面中完成,请见下面的示例:

复制代码
<%@ Register Assembly="Shield.Web.UI"
Namespace="Shield.Web.UI" TagPrefix="shield" %>

因为这个控件其实是对一个客户端 JavaScript 组件的服务端封装,我们还需要引用基础的 JavaScript 图表文件,同样也在.aspx 文件中完成:

复制代码
<head>
<link rel="stylesheet" type="text/css"
href="shield-chart.1.2.2-Trial/shield-chart.1.2.2-Trial/css/shield-chart.min.css"/>
<script src="shield-chart.1.2.2-Trial/shield-chart.1.2.2-Trial/js/jquery-1.9.1.min.js"
type="text/javascript"></script>
<script src="shield-chart.1.2.2-Trial/shield-chart.1.2.2-Trial/js/shield-chart.all.min.js"
type="text/javascript"></script>
</head>

接下来就是要将需求转化为代码了,需求中表示我们需要两个或者更多的图表。在这个示例中,我们将使用一个图表显示所有的季度,另外用一个图表显示每个季度的相关数据,最后还有一个图表与第二个图表相关联。这样,我们就可以按照季度和产品线进行分类,这对于销售仪表板来说是一种常见的数据可视化场景。按照以上所概括的步骤,让我们首先将第一个图表加入.aspx 文件中。它的声明部分如下所示:

复制代码
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional"
ChildrenAsTriggers="false">
<ContentTemplate>
<shield:ShieldChart ID="ShieldChart1" runat="server" AutoPostBack="true"
OnSelectionChanged="ShieldChart1_SelectionChanged" Width="320px" Height="330px"
OnTakeDataSource="ShieldChart1_TakeDataSource">
<PrimaryHeader Text="Quarterly Sales">
</PrimaryHeader>
<ExportOptions AllowExportToImage="false" AllowPrint="false" />
<TooltipSettings CustomPointText="Sales Volume: <b>{point.y}</b>">
</TooltipSettings>
<Axes>
<shield:ChartAxisX CategoricalValuesField="Quarter">
</shield:ChartAxisX>
<shield:ChartAxisY>
<Title Text="Quarter verview"></Title>
</shield:ChartAxisY>
</Axes>
<DataSeries>
<shield:ChartBarSeries DataFieldY="Sales">
<Settings EnablePointSelection="true" EnableAnimation="true">
<DataPointText BorderWidth="">
</DataPointText>
</Settings>
</shield:ChartBarSeries>
</DataSeries>
<Legend Align="Center" BorderWidth=""></Legend>
</shield:ShieldChart>
</ContentTemplate>
</asp:UpdatePanel>

这里用一个 update panel 将控件包装起来,以提供更平滑的视觉上的更新。

为了将数据加载到图表控件中,我们利用了 TakeDataSource 这个事件处理器,以下是.aspx 文件的 code behind 中的部分代码:

复制代码
protected void ShieldChart1_TakeDataSource(object sender,Shield.Web.UI.
ChartTakeDataSourceEventArgs e)
{
ShieldChart1.DataSource = new object[]
{
new {Quarter = "Q1", Sales = 312 },
new {Quarter = "Q2", Sales = 212 },
new {Quarter = "Q3", Sales = 322 },
new {Quarter = "Q4", Sales = 128 }
};
}

控件的 DataSource 属性告诉了图表需要传递给它以实现可视化的数据是什么。我们传入了一个简单的对象数组,它包含了每个季度的销售数据,这样图表就可以表现出每个季度的数据了。接下来将第二个相关的图表也加入.aspx 文件中,看起来是这样的:

复制代码
<div id="container2" style="width: 490px; height: 340px; margin: auto; top: 5px;
left: 5px; position: inherit;">
<asp:UpdatePanel ID="UpdatePanel1" runat="server" pdateMode="Conditional"
ChildrenAsTriggers="false">
<ContentTemplate>
<shield:ShieldChart ID="ShieldChart2" nTakeDataSource="ShieldChart2_
TakeDataSource" AutoPostBack="true"
OnSelectionChanged="ShieldChart2_SelectionChanged" runat="server"
Width="463px" Height="331px">
<ExportOptions AllowExportToImage="false" AllowPrint="false" />
<PrimaryHeader Text="Select a Quarter to show products sales">
</PrimaryHeader>
<Axes>
<shield:ChartAxisY>
<Title Text="Break-Down for selected quarter"></Title>
</shield:ChartAxisY>
</Axes>
<DataSeries>
<shield:ChartDonutSeries EnableValueXSorting="false" ollectionAlias="Q
Data" DataFieldY="Data" DataFieldX="Product">
<Settings EnablePointSelection="true" EnableAnimation="true"
AddToLegend="true">
<DataPointText BorderWidth="">
</DataPointText>
</Settings>
</shield:ChartDonutSeries>
</DataSeries>
<Legend Align="Center" BorderWidth=""></Legend>
</shield:ShieldChart>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ShieldChart1" EventName="SelectionChanged" />
</Triggers>
</asp:UpdatePanel>
</div>

第一和第二个图表控件都应用了一个被选择的事件处理器,以允许对相关控件进行重建,因为他们各自带有一个子图表。这个项目允许最终用户在“SheidChart1”控件以可视化方式显示的 4 个季度选择一个季度。接下来,对所选中的季度,“ShieldChart”控件会以饼图的方式显示所有可用的数据。用户接下来可以从饼图中选择一个特定的分类,这又载入了第三个图表的数据。它的定义如下所示:

复制代码
<div id="container3_box" style="width: 925px; height: 300px; border: 2px solid #40B3DF;
margin: auto; top: 420px; left: 25px; position: absolute;">
<div id="container3" style="width: 890px; height: 290px; margin: auto; top: 5px;
left: 5px; position: inherit;">
<asp:UpdatePanel ID="UpdatePanel3" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<shield:ShieldChart ID="ShieldChart3" runat="server" nTakeDataSource=
"ShieldChart3_TakeDataSource"
Width="905px" Height="280px">
<DataSeries>
<shield:ChartLineSeries DataFieldY="QuarterSales">
<Settings AddToLegend="false">
<DataPointText BorderWidth="">
</DataPointText>
</Settings>
</shield:ChartLineSeries>
</DataSeries>
<PrimaryHeader Text="Select a product to show sales details...">
</PrimaryHeader>
<ExportOptions AllowExportToImage="false" AllowPrint="false" />
<Legend Align="Center" BorderWidth=""></Legend>
</shield:ShieldChart>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ShieldChart2" EventName="SelectionChanged" />
</Triggers>
</asp:UpdatePanel>
</div>
</div>

为了允许对子图表进行重建,还需要加入一个额外的步骤。这一步是当图表被选择的事件触发后在服务端完成的,这样就可以避免编写客户端代码了。具体的服务端代码如下所示:

复制代码
protected void ShieldChart1_SelectionChanged(object sender,
ChartSelectionChangedEventArgs e)
{
if (e.Selected)
{
SelectedQuarter = e.Name;
DataPerformance = GetPerformanceData().Where(d => d.Quarter == electedQuarter).
ToList();
}
else
{
DataPerformance = null;
}
ShieldChart2.DataBind();
}
protected void ShieldChart2_SelectionChanged(object sender,
ChartSelectionChangedEventArgs e)
{
if (e.Selected)
{
SalesData = GetSalesDataProducts().Where(s => s.Quarter == SelectedQuarter &&
s.Product == e.Item.ValueX.ToString()).ToList();
}
else
{
SalesData = null;
}
ShieldChart3.DataBind();
}

以上就完成了 ASP.NET 的版本,销售仪表板已经可以使用了。请随意下载该示例代码并作为今后的参考。

MVC 应用程序

这个示例也可以很方便地搭建在 MVC 上。首先建立一个新的 Visual Studio 2012 MV 应用程序,使用.NET Framework 4.0。为了使用图表控件的功能,我在项目中添加了对 Shield.Mvc.UI 这个 dll 文件的引用:

以下是该应用程序的文件夹结构:

接下来我会逐一地讲解每个文件夹中令人感兴趣的部分,并讲述一些代码之外的信息,以及每段代码的重要性。首先从 Views 文件夹开始,它包含了四个不同的视图,三个用来显示图表,另一个则包含主体页面结构。第一个视图是“Layout.cshtml”,它决定了页面的主体结构,并且加入了图表组件与它的封装所需的各种 css 文件与 js 文件的引用。

复制代码
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Sales Dashboard - Shield Chart for ASP.NET MVC</title>
<link rel="stylesheet" type="text/css" href="content/shield-chart.1.2.3-
Trial/css/shield-chart.min.css" />
<script src="content/shield-chart.1.2.3-Trial/js/jquery-1.9.1.min.js"
type="text/javascript"></script>
<script src="content/shield-chart.1.2.3-Trial/js/shield-chart.all.min.js"
type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="content/css/site.css" />
<script src="content/js/scripts.js" type="text/javascript"></script>
</head>
<body>
<div class="page">
<div class="header">
</div>
<div class="main">
@RenderBody()
</div>
<div class="clear">
</div>
</div>
<div class="footer">
</div>
</body>
</html>

该视图中还包含了一个对“scripts.js”的引用,这个文件包含了客户端事件的处理器,但本文的末尾部分讨论了该文件的更多细节。

下一个视图“Index.cshtml”包含了“季度”图表的定义,这是唯一一个会在初始化页面时就显示的图片,选择这张图表上的某个季度就会加载相应的饼图。这个视图的声明部分包括了设置控件的各种必需属性,例如它的 X 轴与 Y 轴,还有 DataSeries 属性以及实际的数据。其中有趣的一点是“Events”属性,它定义了从条状图中选择某个点之后的事件处理器,这一点对于关联图表与子图表非常关键,当用户从第一张图表中选择了某个季度后,子图表就会显示相应的数据。该页面的代码如下所示:

复制代码
@{
ViewBag.Title = "Sales Dashboard with Shield Chart for ASP.NET MVC";
Layout = "~/Views/Shared/Layout.cshtml";
}
@model IEnumerable<SalesDashboardMVC.Models.QuarterlySales>
<div class="dashboard">
<div class="header">
Sales DashBoard using <span class="highlight">Shield
UI MVC Chart</span>
</div>
<div class="topleft">
@(Html.ShieldChart(Model)
.Name("quarterlySales")
.HtmlAttribute("class", "chart")
.PrimaryHeader(header => header.Text("Quarterly Sales"))
.Export(false)
.Tooltip(tooltip => tooltip.CustomPointText("Sales Volume: <b>{point.y}</b>"))
.AxisX(axisX => axisX.CategoricalValues(model => model.Quarter))
.AxisY(axisY => axisY.Title(title => title.Text("Quarterly Overview")))
.DataSeries(dataSeries => dataSeries
.Bar()
.Data(model => model.Sales)
.EnablePointSelection(true))
.ChartLegend(chartLegend => chartLegend
.Align(Shield.Mvc.UI.Chart.Align.Center))
.Events(events => events.PointSelect("app.quarterSelected")))
</div>
<div class="topright">
</div>
<div class="bottom">
</div>
</div>

当用户从页面初始化时就显示的条状图中选择了某个季度后,第一个子图表就会加载相应的数据,并显示为一个饼图。它的定义包含在“_PerformanceChart.cshtml”视图中,代码如下所示:

复制代码
@model IEnumerable<SalesDashboardMVC.Models.PerformanceData>
@(Html.ShieldChart(Model)
.Name("productsByQuarter")
.HtmlAttribute("class", "chart")
.Export(false)
.PrimaryHeader(header => header.Text("Select a Quarter to show products sales"))
.AxisY(axisY => axisY.Title(title => title.Text("Break-Down for selected quarter")))
.DataSeries(dataSeries => dataSeries
.Donut()
.Name("Q Data")
.Data(model => new
{
collectionAlias = model.Product,
x = model.Product,
y = model.Data,
})
.EnablePointSelection(true)
.AddToLegend(true))
.ChartLegend(chartLegend => chartLegend.Align(Shield.Mvc.UI.Chart.Align.Center))
.Events(events => events.PointSelect("app.productSelected")))

当用户选择了饼图里的某一项之后,就会加载数据并显示最后一张图表。它的代码包含在“_SalesDetailsChart.cshtml”文件中,具体定义如下:

复制代码
@model IEnumerable<SalesDashboardMVC.Models.SalesByProduct>
@(Html.ShieldChart(Model)
.Name("salesDetails")
.HtmlAttribute("class", "chart")
.PrimaryHeader(header => header.Text("Select a product to show sales details"))
.Export(false)
.DataSeries(dataSeries => dataSeries
.Line()
.Data(model => model.QuarterSales)
.AddToLegend(false)))

“Models”文件夹包含了数据的模型,它将用以加载三个不同的图表。举例来说,首个图表将对应类型“QuarterlySales”中的数据,它的代码如下:

复制代码
namespace SalesDashboardMVC.Models
{
public class QuarterlySales
{
public string Quarter { get; set; }
public decimal Sales { get; set; }
public static IEnumerable<QuarterlySales> GetData()
{
yield return new QuarterlySales() { Quarter = "Q1", Sales = 312 };
yield return new QuarterlySales() { Quarter = "Q2", Sales = 212 };
yield return new QuarterlySales() { Quarter = "Q3", Sales = 322 };
yield return new QuarterlySales() { Quarter = "Q4", Sales = 128 };
}
}

其它图表也将对应类似的数据类,我在这里就略过不提了。“Controllers”文件夹包含了一个单独的控制器,它将响应图表的选择所对应的各种行为。代码如下:

复制代码
public class HomeController: Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View(QuarterlySales.GetData());
}
public ActionResult Performance(string quarter)
{
return View("_PerformanceChart",
PerformanceData.GetDataByQuarter(quarter));
}
public ActionResult Details(string product, string quarter)
{
return View("_SalesDetailsChart", alesByProduct.
GetDataByProductAndQuarter(product, quarter));
}
}

有一段重要的代码需要引起注意,那就是“Content”文件夹下的“scripts.js”文件。从以上的代码声明可以看出,第一与第二个图表包括了选择事件的处理器。这些处理器将处理客户端的事件,这是由用户在条状图或饼图中选择了一段数据所触发的,而“scripts.js”文件则包含了这些事件的客户端处理器,它的代码如下:

复制代码
(function (jQuery) {
this.app = {
quarter: "",
quarterSelected: function (e) {
var quarter = app.quarter = e.point.name;
$(".topright").load("/performance/" + quarter);
$(".bottom").empty();
},
productSelected: function (e) {
var product = e.point.x,
quarter = app.quarter;
$(".bottom").load("/details/" + product + "/" + quarter);
}
};
}).call(this, jQuery);

实质上,这段代码会发起一个 Ajax 请求,它将处理被选择的数据,而这是由方法的参数中传递的。该请求将触发“Performance”或者“Details”的行为处理器,它们都由“HomeController”中的控制器所定义。

我们的代码中最主要的部分到这里差不多就介绍完了,完整的代码和一个可运行的项目都可以在这里下载。

关于作者

David Johnson来自于英国伦敦,他已经是一位 37 岁的“老”程序员了。过去的 15 年来他主要工作于 web 技术的领域,而过去 10 年中他主要专注于 ASP.NET 和 MVC 平台。David 作为一名外包开发者参与了许多项目,最近的职位是在 ShieldUI 担任首席开发者。

查看英文原文: Creating a sales dashboard for ASP.NET and MVC with ShieldUI Chart

2013-12-11 21:502827
用户头像

发布了 428 篇内容, 共 196.5 次阅读, 收获喜欢 39 次。

关注

评论

发布
暂无评论
发现更多内容

关于稳定扩散最详细的介绍

3D建模设计

人工智能 Stable Diffusion AI自动纹理 稳定扩散

软件测试/测试开发丨接口测试Mock实战练习学习笔记

测试人

软件测试 接口测试 Mock

云服务器数据安全保障措施看这里!

行云管家

云计算 云安全 云服务器 云数据

入门指导:NGINX 中的 QUIC 网络连接和加密

NGINX开源社区

DNS DDoS QUIC nginx 开源版 HTTP/3

【慢SQL性能优化】 一条SQL的生命周期 | 京东物流技术团队

京东科技开发者

MySQL 数据库 SQL优化 企业号11月PK榜

一种简化操作日志记录方案 | 京东云技术团队

京东科技开发者

日志 系统 日志记录 企业号11月PK榜

一文了解亚马逊云科技最新大语言模型

苏沐

大模型 亚马逊 亚马逊云科技 向量数据库

YonGPT构筑酒旅企业AI大脑 轻松拿捏“松弛感”

用友BIP

AI YonGPT

企业如何选型iPaaS平台

谷云科技RestCloud

ipaas

沉浸式LED显示屏的定义和特点

Dylan

LED显示屏 沉浸式体验 沉浸式

软件研发流程、架构规范、技术标准、需求过程等全文档

代码人,代码魂

开发文档

向成本要效益!用友BIP助力车企突破内卷、打赢“降本战”

用友BIP

降本增效

大模型产业生态有“成功密码”?百度高管2023进博会最新发声

飞桨PaddlePaddle

深度学习 产业生态 大模型

淘天Java一面,难度适中!(上篇)

王磊

Java java面试

前端计算数字精度丢失问题解决方法记录 | 京东云技术团队

京东科技开发者

前端 企业号11月PK榜 数字精度

可测性,到底是什么?

老张

质量保障 质量门禁

搜狐基金使用 MySQL 遇到瓶颈?来看 TDengine 如何解决难题

TDengine

tdengine 时序数据库 搜狐基金

快速教程|如何在 AWS EC2上使用 Walrus 部署 GitLab

SEAL安全

#GitLab Walrus 企业号11月PK榜

软件测试/测试开发丨探索Python魔力:第一个程序到快捷键大揭秘

测试人

Python 软件测试

大模型集体失控!南洋理工新型攻击,主流AI无一幸免

Openlab_cosmoplat

人工智能 大模型

有效降低数据库存储成本方案与实践 | 京东云技术团队

京东科技开发者

数据库 存储 数据存储 降本 企业号11月PK榜

文件传输|如何将100多G文件跨国安全传输到客户手里呢?

镭速

跨国文件传输

孵化Web3区块链技术系统开发

l8l259l3365

支持企业微信集成和登录!镭速传输新版本带来多项升级

镭速

镭速

LTV预测算法从开发到上线,浅谈基于奇点云DataSimba的MLOps实践

极客天地

Stable Diffusion:最先进的文本生成图像模型

3D建模设计

人工智能 Stable Diffusion 稳定扩散 自动纹理

为什么说数据安全运维难?有好用的数据安全运维平台吗?

行云管家

数字化 数据安全 数据运维 数据运维安全

高性价比AWS Lambda无服务体验

查拉图斯特拉说

Lambda 亚马逊云科技 Amazon Lambda

数仓实践丨表扫描时过滤行数过多引起的性能瓶颈问题

华为云开发者联盟

数据库 数据仓库 后端 华为云 华为云开发者联盟

使用shieldUI Chart控件在ASP.NET和MVC应用程序中创建一个销售仪表板_语言 & 开发_David Johnson_InfoQ精选文章