在大多數(shù)情況下,我們的Web程序不僅僅需要給用戶提供具體數(shù)據(jù),在一些情況下,我們還需要給高級(jí)的用戶或管理者提供數(shù)據(jù)匯總和分析圖表之類的功能。
如果我們不想顯示一大堆煩心的數(shù)據(jù),希望通過餅圖或條形圖來直觀地顯示數(shù)據(jù),這是我們可以考慮使用圖表控件顯示。
在接下來的文章中,我們將向大家介紹數(shù)據(jù)儀表板程序的實(shí)現(xiàn)。
之前有一篇文章關(guān)于StackOverflow上的編程趨勢(shì),它通過條形和區(qū)域圖,向我們展示了Stackoverflow上的熱門的問題標(biāo)簽。
圖1 Stackoverflow的熱門標(biāo)簽
通過上圖,我們可以直觀地了解Stackoverflow上的熱門標(biāo)簽的變化趨勢(shì),現(xiàn)在,我們通過儀表程序?qū)崿F(xiàn)同樣的功能。
在儀表程序界面中,我們會(huì)通過餅狀圖、區(qū)域圖和條形圖顯示數(shù)據(jù),這里我們使用Google Charts控件來顯示餅狀圖、區(qū)域圖和條形圖數(shù)據(jù)圖。
Google Charts通過Javascript實(shí)現(xiàn)動(dòng)態(tài)圖片的繪制,它的使用非常簡(jiǎn)便,我們只需給相應(yīng)的繪圖函數(shù)傳遞相應(yīng)的數(shù)據(jù),就可以生成相應(yīng)的數(shù)據(jù)圖表了。
UI設(shè)計(jì)
圖2 Dashboard界面
現(xiàn)在,我們要在主界面(Dashboard)中,顯示數(shù)據(jù)的餅狀圖、區(qū)域圖和條形圖,那么我們使用Google Charts控件動(dòng)態(tài)地把三種圖形加載到Index.cshtml頁面中,下面是Index.cshtml頁面代碼:
!-- Dashboard UI START -->
body>
div>
@{ Html.RenderAction("Dashboard_Pie", "DashBoard"); }
/div>
div>
@{ Html.RenderAction("Dashboard_AreaChart", "DashBoard"); }
/div>
div>
@{ Html.RenderAction("Dashboard_ColumnChart", "DashBoard"); }
/div>
/body>
!-- Dashboard UI END -->
上面,我們定義了三個(gè)div元素,Index.cshtml頁面動(dòng)態(tài)地加載Dashboard_Pie、Dashboard_AreaChart以及Dashboard_ColumnChart的內(nèi)容。
接下來,我們要定義Dashboard_Pie(餅狀圖)、Dashboard_AreaChart(區(qū)域圖)和Dashboard_ColumnChart(條形圖)頁面,在定義數(shù)據(jù)圖界面之前,首先讓我們介紹Google Charts的使用。
Javascript
前面我們提到Google Charts的使用十分方便,首先我們需要引用jsapi庫,在頁面代碼中添加如下代碼:
!-- Adds Google js api reference.-->
script type="text/javascript" src="https://www.google.com/jsapi">/script>
Google的JSAPI,不僅可以加載Google自身提供的AJAX API(如:Google Map API、Google Search API和Google Earth API),它還可以加載各種常用的JS庫(如:jQuery、jQuery UI、Prototype、MooTools和Dojo等)。
現(xiàn)在,我們?cè)陧撁嬷刑砑尤缦翵avascript代碼,引用Google的visualization庫:
script type="text/javascript">
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawPieChart);
/script>
上面,我們使用google的load()方法加載了visualization庫,并且定義了加載成功后的回調(diào)函數(shù)為drawPieChart()。
也許有人會(huì)問:“為什么不直接用Google CDN中提供Javascript庫呢?”有兩個(gè)原因,首先我們?cè)贕oogle CDN中沒有找到和visualization庫相關(guān)的引用地址(如有請(qǐng)告訴一下),其次,google的load()方法會(huì)加載一系列相關(guān)的資源(如:Javascript和CSS),這樣我們就無需一個(gè)個(gè)引用了。
前面,我們定義了回調(diào)函數(shù)drawPieChart(),但還沒有實(shí)現(xiàn)該方法,接下來,我們需要實(shí)現(xiàn)回調(diào)函數(shù)drawPieChart(),它負(fù)責(zé)獲繪制數(shù)據(jù)圖,具體實(shí)現(xiàn)如下:
/**
* Draws the pie chart.
**/
function drawPieChart() {
// Gets data from GetLanguageRank().
$.ajax({
type: 'GET',
dataType: 'json',
url: '%= Url.Content("") %>',
data: {},
success: function(data) {
var dt = new google.visualization.DataTable();
dt.addColumn('string', 'Language');
dt.addColumn('number', 'Question');
// Adds data.
for (var i = 0; i data.length; i++) {
dt.addRow([data[i].Name, data[i].Question]);
}
var options = {
title: "Top 25 programming language"
};
// Draws pie implemention.
var chart = new google.visualization.PieChart(document.getElementById('pieChart'));
chart.draw(dt, options);
},
error: function(xhr, textStatus, e) {
console.log('Status: ' + textStatus + ' Error: ' + e.toString());
},
complete: function() {
}
});
}
上面,我們實(shí)現(xiàn)了回調(diào)函數(shù)drawPieChart(),它通過調(diào)用$.ajax()方法從后端中獲取數(shù)據(jù),如果數(shù)據(jù)獲取成功,就把數(shù)據(jù)傳遞給draw()方法繪制數(shù)據(jù)圖表。
接著,我們實(shí)現(xiàn)Dashboard_Pie數(shù)據(jù)圖界面,具體代碼如下:
!-- Pie chart page -->
!DOCTYPE html>
html xmlns="http://www.w3.org/1999/xhtml">
head id="Head1" runat="server">
meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
title>/title>
/head>
body>
form id="form2" runat="server">
div id="pieChart">
/div>
/form>
/body>
/html>
上面,我們?cè)趂orm元素中添加了一個(gè)div元素,由于我們?cè)诨卣{(diào)函數(shù)drawPieChart()中,指定了餅狀圖的加載位置,所以我們需要在頁面中添加餅狀圖的div元素。
前面,我們提到回調(diào)函數(shù)drawPieChart(),通過$.ajax()方法從后端中獲取數(shù)據(jù),現(xiàn)在,我們需要提供API方法,讓客戶端通過調(diào)用API獲取相應(yīng)的數(shù)據(jù)。
這里,我們使用Stackoverflow Jan/01/2010到July/01/2013的熱門標(biāo)簽數(shù)據(jù)。
由于數(shù)據(jù)是CSV格式的,所以我們可以使用Excel查看數(shù)據(jù)。
圖3 熱門標(biāo)簽數(shù)據(jù)
通過上圖中的數(shù)據(jù),我們定義Language類,它包含四個(gè)字段分別是Id、Name、Question和CreateOn,具體定義如下:
圖4 Language類
/// summary>
/// The language model.
/// /summary>
public class QuestionTag
{
public int Id { get; set; }
public string Name { get; set; }
public int Question { get; set; }
public DateTime CreateOn { get; set; }
}
上面,我們定義了QuestionTag類,接下來,我們需要定義控制器類,它負(fù)責(zé)返回后端數(shù)據(jù),所以我們?cè)贑ontrollers文件中創(chuàng)建DashboardController類,并且我們添加GetLanguageRank()方法,具體實(shí)現(xiàn)如下:
圖5 DashboardController類
/// summary>
/// Gets language rank data.
/// /summary>
/// returns>JSON arrary./returns>
public JsonResult GetLanguageRank()
{
// Gets data from database.
}
導(dǎo)入數(shù)據(jù)
上面,我們定義了DashboardController類,它包含GetLanguageRank()方法,接下來我們把CSV數(shù)據(jù)保存到數(shù)據(jù)庫中。首先,我們?cè)跀?shù)據(jù)庫中創(chuàng)建數(shù)據(jù)表,具體SQL代碼如下:
-- =============================================
-- Description: Table for storing question tag data
-- =============================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[QuestionTags](
[Name] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
[Question] [int] NOT NULL,
[CreateOn] [datetime] NOT NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
接著,我們CSV數(shù)據(jù)導(dǎo)入到SQL Server中,具體實(shí)現(xiàn)如下:
-- =============================================
-- Description: Imports csv data into database.
-- =============================================
BULK INSERT QuestionTags
FROM 'C:\Users\Administrator\Desktop\Stackoverflow Tags Data.csv'
WITH
(
FIRSTROW = 2, -- Start row excludes header.
FIELDTERMINATOR = ',', --CSV field delimiter
ROWTERMINATOR = '\n', --Use to shift the control to next row
ERRORFILE = 'C:\Users\Administrator\Desktop\ErrorLog.csv',?
TABLOCK
)
上面,我們直接使用SQL語句把CSV數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫中,其中,我們定義了導(dǎo)入數(shù)據(jù)的源文件和數(shù)據(jù)格式,并且定義了ErrorLog文件記錄導(dǎo)入失敗的數(shù)據(jù),最后,我們?cè)诒鞶uestionTags中添加自增型的Id主鍵。
圖6 導(dǎo)入CSV數(shù)據(jù)
ASP.NET控制器
現(xiàn)在,我們已經(jīng)把數(shù)據(jù)儲(chǔ)存到數(shù)據(jù)庫中了,接下來我們將使用EF獲取數(shù)據(jù)庫中的數(shù)據(jù),接觸過EF的應(yīng)該都知道EF的編程模型有3種:
- Database First:數(shù)據(jù)庫先行
- Model First:模型先行
- Code First:代碼先行
由于,前面我們已經(jīng)把數(shù)據(jù)表定義好了,所以我們將使用數(shù)據(jù)庫先行(Database First)模型對(duì)數(shù)據(jù)庫進(jìn)行訪問。
接下來,讓我們實(shí)現(xiàn)GetLanguageRank()方法,具體代碼如下:
/// summary>
/// Gets language rank data.
/// /summary>
/// param name="index">Specifies the range of data,
/// for instance, when index is 0, then get the data range from Jan/1/2010 till Feb/2/2010.
/// /param>
/// returns>JSON Array/returns>
public JsonResult GetLanguageRank(int index = 0)
{
using (var db = new DashboardDbContext())
{
var result = (from tags in db.QuestionTags
orderby tags.CreateOn ascending
select new { tags.Id, tags.Name, tags.Question, tags.CreateOn }).Skip((index % 42) * 25).Take(25).ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
}
我們實(shí)現(xiàn)了GetLanguageRank()方法,它根據(jù)index值獲取指定時(shí)間的數(shù)據(jù),然后通過JSON數(shù)據(jù)格式返回給客戶端。
現(xiàn)在,我們已經(jīng)實(shí)現(xiàn)了餅狀圖(Dashboard_Pie)了,接下來,讓我們運(yùn)行Index.cshtml頁面查看運(yùn)行的效果吧!
圖7 餅狀圖
我們注意到圖1是一個(gè)動(dòng)態(tài)圖,它直觀的展示了Stackoverflow熱門標(biāo)簽的變化趨勢(shì),如果我們也要實(shí)現(xiàn)動(dòng)態(tài)生成數(shù)據(jù)圖該如何實(shí)現(xiàn)呢?
其實(shí),問題轉(zhuǎn)化為實(shí)時(shí)獲取數(shù)據(jù),然后生成數(shù)據(jù)圖就OK了,如果要實(shí)現(xiàn)實(shí)時(shí)獲取時(shí)間,我們想到的方法有:
- 1.Timer()
- 2.方法二數(shù)據(jù)庫實(shí)時(shí)方法數(shù)據(jù)(SqlDependency)
- 3.Other(請(qǐng)大家分享好方法)
接下來,我們將使用Javascript中Timer()函數(shù)來定時(shí)訪問GetLanguageRank()方法,所以我們需要修改Javascript代碼,通過Timer()函數(shù)定時(shí)調(diào)用drawColumnChart()方法,具體實(shí)現(xiàn)如下:
script type="text/javascript">
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(timerStart);
var cnt = 0, t;
function timerStart() {
t = window.setInterval(drawColumnChart, 1000);
}
function timerStop() {
clearTimeout(t);
}
function drawColumnChart() {
$.ajax({
type: 'GET',
dataType: 'json',
url: '%= Url.Content("~/Dashboard/GetLanguageRank") %>',
data: { index: cnt },
success: function(data) {
var dt = new google.visualization.DataTable();
dt.addColumn('string', 'Language');
dt.addColumn('number', 'Question');
for (var i = 0; i data.length; i++) {
dt.addRow([data[i].Name, data[i].Question]);
}
var dateTime = new Date(parseInt(data[0].CreateOn.substr(6)));
var options = {
title: "Top 25 programming language on " +
(dateTime.getMonth() + 1) + '/' + dateTime.getDate() + '/' + dateTime.getFullYear(),
//width: 600,
height: 500
};
var chart = new google.visualization.ColumnChart(document.getElementById('columnChart'));
chart.draw(dt, options);
},
error: function(xhr, textStatus, e) {
timerStop();
console.log('Status: ' + textStatus + ' Error: ' + e.toString());
},
complete: function() {
cnt = cnt + 1;
}
});
}
/script>
當(dāng)Google的visualization庫加載完畢后,訪問回調(diào)函數(shù)timerStart(),然后使用setInterval()方法每隔1s就調(diào)用drawColumnChart()繪制新的柱狀圖。
圖8 柱狀圖
現(xiàn)在,我們通過Timer()函數(shù)實(shí)時(shí)的訪問API接口,數(shù)據(jù)通過柱狀圖動(dòng)態(tài)地顯示出來。
頁面樣式
現(xiàn)在,我們已經(jīng)完成了餅狀圖和柱狀圖,接下來,我們需要給儀表程序添加一些簡(jiǎn)單的CSS效果,具體代碼如下:
/*Dashboard APP CSS*/
.pageHeader
{
height: 20px;
background-color: #2C2C2C;
padding: 10px 10px;
margin-bottom: 10px;
color: White;
position: relative;
}
.pageHeader h1
{
font: normal 1.2em Arial;
color: White;
margin: 0;
padding: 0;
}
.pageHeader .platformular
{
position: absolute;
top: 10px;
right: 10px;
}
.pageBody
{
margin: 0 10px;
}
.pageFooter
{
clear: both;
padding-top: 10px;
width: 100%;
text-align: center;
font-size: 0.8em;
color: #686868;
margin: 25px 0 0 0;
border-top: solid 1px #e7e7e7;
}
現(xiàn)在,我們重新運(yùn)行程序查看頁面效果。
圖10儀表程序
在本文中,我們通過使用ASP.NET MVC和EF的Database First實(shí)現(xiàn)了簡(jiǎn)單的儀表程序,使用Google Charts控件來顯示數(shù)據(jù)圖,這只是一個(gè)簡(jiǎn)單的程序,我們還有很大的改善空間,提供一個(gè)內(nèi)容豐富和功能強(qiáng)大的程序是每個(gè)程序員的目標(biāo)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
您可能感興趣的文章:- 解決asp.net mvc UpdateModel更新對(duì)象后出現(xiàn)null問題的方法
- ASP.NET MVC命名空間時(shí)引起錯(cuò)誤的解決方法
- ASP.NET Mvc開發(fā)之EF延遲加載
- ASP.NET Mvc開發(fā)之查詢數(shù)據(jù)
- ASP.NET Mvc開發(fā)之刪除修改數(shù)據(jù)
- ASP.NET MVC中HtmlHelper控件7個(gè)大類中各個(gè)控件使用詳解
- 詳解ASP.NET MVC Form表單驗(yàn)證
- ASP.NET MVC4 HtmlHelper擴(kuò)展類,實(shí)現(xiàn)分頁功能
- asp.net MVC利用自定義ModelBinder過濾關(guān)鍵字的方法(附demo源碼下載)
- ASP.NET MVC使用ActionFilterAttribute實(shí)現(xiàn)權(quán)限限制的方法(附demo源碼下載)
- ASP.NET MVC @Helper輔助方法和@functons自定義函數(shù)的使用方法