写点什么

使用 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:502479
用户头像

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

关注

评论

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

圣雄能源电石厂:“一机一码”,助力巡检新格局

草料二维码

设备巡检管理系统 草料二维码 设备巡检二维码 设备巡检系统 设备管理软件

实用的防休眠工具 Caffeinated for Mac v2.0.6激活版

Rose

场景应用|AR远程协作之——远程验收

AR玩家

AR Rokid Vision pro 炬目AR AR远程协作

Royal TSX常见问题:解决远程桌面(RDP)连接错误

Rose

远超美国!中国AI专利数量全球第一!商汤推出面向C端用户大模型“Vimi”,可生成分钟级视频!|AI日报

可信AI进展

人工智能

数据工程(二):数据需求管理,解锁信息宝藏的“指南针”

数造万象

工具 需求管理 数据工程

财会监督 |合同风险管理:企业风险控制的精准锚点

用友BIP

Live Home 3D Pro(3D家庭室内设计工具)支持3D渲染和虚拟漫游功能

Rose

Things3 for Mac(日程和任务管理工具) v3.20.8中文免激活版

Rose

让AI成为教师的“好帮手”,英特尔联合希沃打造更懂教师的教学神器

E科讯

Eudic 欧路词典 for Mac 英语词典翻译查询工具 v4.6.7激活版

Rose

Path Finder:Mac平台上的一款功能强大的文件管理工具

Rose

PPSSPPSDL for mac(PSP游戏模拟器)附PSP游戏安装包 v1.17.1激活版

Rose

AI+采购丨精益每一步,敏捷每一刻,数智采购的进化之路

用友BIP

企业数智化首选!众多行业领先企业选择用友BIP,实现业务敏捷

用友BIP

下课10分钟,AI都做了什么?

E科讯

最强GTD时间管理工具 OmniFocus Pro 3 for Mac 附注册码

Rose

三年级课堂上演投影仪“消失术“,英特尔与希沃有话说

E科讯

GreatSQL中 Insert 慢是什么情况?

GreatSQL

CorelDRAW Mac破解版,CorelDRAW序列号最新,cdr平面设计

Rose

Syncaila for Mac(多机位自动对视频音频同步工具) v2.1.4激活版

Rose

3CX的具体介绍

cts喜友科技

通信 通讯 云通讯

Ample Sound Ample Guitar Twelve for Mac(12弦吉他)

Rose

寻找适合编写静态分析规则的语言

华为云开发者联盟

软件开发 华为云 静态分析 华为云开发者联盟 企业号2024年7月PK榜

AI+,企业最期待的是什么?

用友BIP

nuke破解版下载 mac影视后期特效合成软件

Rose

“内卷”的电商江湖:拼服务才有出路

Alter

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