2013年12月30日 星期一

KendoUI & ASP.NET MVC系列文章

前言

在ASP.NET WebForm我們有非常多的伺服器控制項,這些控制項減少了Web程式設計師很多工,隨著技術演進,前端技術越來越火紅,越來越多JavaScript函式庫出現(JQuery、knockout.js、Angular.js…),就連UI套件也有JQuery UI、EasyUI、jqGrid等等出現…。開發ASP.NET MVC時,並沒有那些伺服器控制項了,前後端拆分越來越明確,所以開始找尋適合自己的UI FreamWork,後來Study到KendoUI這個套件,開發上還蠻順利的,至於為什麼不用WebForm+KendoUI呢?是因為我覺得Webform本身架構不太適合Ajax,還是用那些伺服器控制項在開發及維護上會好一點(慘痛經驗QQ) !

KendoUI

KendoUI是以Telerik公司推出以JQuery為基礎加上Html5,CSS3的FreamWork,雖然說是HTML5/CSS3,但對於瀏覽器相容器支持度也沒少,且還有針對行動裝置有KendoUI Mobile,因為是以JQuery為基底,對於常使用JQuery開發的我而言,語法都有些親切感,筆者也用過JQuery UI一陣子,但相較之下,我更喜歡KendoUI的配色主題(個人喜好)。就以ASP.NET而言,KendoUI分為Open Source和付費版本,付費版本多了很多MVC的Helper,且享有技術支援,而Open Source授權部分,只要你不把你的網站包成產品販賣,不管是外網使用或公司內部使用都不會有問題,詳細授權的相關問題可看黑暗大的此篇-AJAX式資料清單的新選擇-Kendo UI Grid
image 

文章目的

本系列文章都會使用Open Sorce版本來實做,在Study這個FreamWork的過程,不免有一些學習曲線,希望將這些零散的筆記整理成文章,讓大家選擇這套UI時,能更快上手,當然,過程中使用ASP.NET MVC架構開發,能讓大家(也讓我),做個記錄順便分享開發心得。而最初的幾篇,我將以使用上最頻繁的Grid控制項先講起,未來會陸續增加文章,也會繼續分享其他控制項的開發心得。




系列文章

KendoUI & ASP.NET MVC系列文章 -  在Visual Studio安裝及更換主題
KendoUI & ASP.NET MVC系列文章 -  基本的Grid功能
KendoUI & ASP.NET MVC系列文章 -  處理CRUD-使用Ajax讀取後端Model資料
KendoUI & ASP.NET MVC系列文章 -  處理CRUD-繼續完成新增、修改、刪除
 


2013年12月27日 星期五

KendoUI & ASP.NET MVC系列文章 - 處理CRUD-繼續完成新增、修改、刪除

前言

前一篇我們已經完成利用Ajax來讀取後端資料顯示於Grid,而此篇就會將新增、修改、刪除功能接續完成

CRUD的 Create - 新增

Controller

利用原本樣板產生的程式做一些修改,原本程式如下

image

將上面程式修改為以下,透過MVC的Model Bindder可以接收前端傳來的Customers物件,並依情況回傳是否新增成功

image

View

將dataSrc新增一個Create function,指向後端的CreateCustomer,並在完成後alert處理結果

 image

Schema部分新增model定義,讓KendoUI知道你的模組結構,並且可設定一些欄位驗證

image

接著在屬性部分新增toolbar及editable,editable模式可分為inline(直接在Gird新增一個)或者是popup(彈跳視窗)方式,此例我們希望新增時是跳出一個燈箱視窗

image

結果圖

這樣就完成,在以往我們可能自己要實做View的頁面,現在KendoUI都幫你做好好的,且表單也排得很整理 lol

image


CRUD的Update-編輯

Controller

基本上跟新增大同小異,我們在Controller新增EditCustomer的JsonResult

image 

View

新增一個Update function

image

在columns多一個command成員,並設定edit按鈕(這邊也可以自訂義Button標籤)

image

這樣就完成編輯燈箱視窗了!!

image

CRUD的Delete-刪除

Contoller (這邊就不解釋了)

image

View

image

image

後記

以上是一種實做CRUD的方式,但其實做法有很多種,譬如你也可自訂新增、編輯的View去實做,或者你也可以自訂一些查詢欄位POST到後端去,關於版面,如果要修改中文的顯示其實也可以做到,之後也會分享一些實做心得PO上來。而下一篇,預計完將後端改成用WebAPI + OData的方式實做 =V=

完成程式碼

Contoller

public class GridAjaxController : Controller
{
private NorthwindEntities db = new NorthwindEntities();

// GET: /GridAjax/
public ActionResult Index()
{
return View();
}

public JsonResult GetCustomer(KendoGridRequest request)
{
try
{
var result = db.Customers.ToList();
return Json(new KendoGrid<Customers>(request, result), JsonRequestBehavior.AllowGet);
}
catch (Exception)
{
Dictionary<string, object> error = new Dictionary<string, object>();
error.Add("ErrorCode", -1);
error.Add("ErrorMessage", "讀取資料失敗!");
return Json(error);
}
}

// GET: /GridAjax/Details/5
public ActionResult Details(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customers customers = db.Customers.Find(id);
if (customers == null)
{
return HttpNotFound();
}
return View(customers);
}

// GET: /GridAjax/Create
public ActionResult Create()
{
return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult CreateCustomer(Customers customers)
{
if (ModelState.IsValid)
{
if (TryUpdateModel(customers))
{
db.Customers.Add(customers);
db.SaveChanges();
return Json("新增成功!!");
}
}
return Json("新增失敗!!");
}

public JsonResult EditCustomer(Customers customers)
{
if (ModelState.IsValid)
{
db.Entry(customers).State = EntityState.Modified;
if (TryUpdateModel(customers))
{
db.SaveChanges();
return Json("更新成功!!");
}
}
return Json("更新失敗!!");
}

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult DeleteCustomer(string CustomerID)
{
Customers customers = db.Customers.Find(CustomerID);
db.Customers.Remove(customers);
if (TryUpdateModel(customers))
{
db.SaveChanges();
return Json("刪除成功!!");
}
return Json("刪除失敗!!");
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}

View

@model IEnumerable<KendoUI.Model.Customers>

@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/BaseLayoutPage.cshtml";
}

@section scripts
{
<script type="text/javascript">
$(function () {

//資料來源物件改用Ajax
var dataSrc = new kendo.data.DataSource({
transport: {
read: {
type: "POST",
url: "/GridAjax/GetCustomer",
dataType: "json",
complete: function (response, status) {
if (response.responseJSON.ErrorCode == -1) {
alert(response.responseJSON.ErrorMessage);
}
}

},
update: {
url: "/GridAjax/EditCustomer",
dataType: "json",
type: "POST",
complete: function (response, status) {
alert(response.responseJSON);
}
},
create: {
url: "/GridAjax/CreateCustomer",
dataType: "json",
type: "POST",
complete: function (response, status) {
alert(response.responseJSON);
}
},
destroy: {
url: "/GridAjax/DeleteCustomer",
dataType: "json",
type: "POST",
complete: function (response, status) {
alert(response.responseJSON);
}
},
},
schema: {
data: function (d) {
return d.data;
},
total: function (d) { return d.total; },
model: {
id: "CustomerID",
fields: {
product: { editable: false, nullable: false },
CompanyName: { validation: { required: true } },
ContactName: { validation: { required: true } },
City: { validation: { required: true } }
}
}
},
pageSize: 5,
serverPaging: true,
serverSorting: true
});

$("#gridData").kendoGrid({
dataSource: dataSrc,
columns: [
{ field: "CustomerID", title: "CustomerID" },
{ field: "CompanyName", title: "CompanyName" },
{ field: "ContactName", title: "ContactName" },
{ field: "City", title: "City" },
{ command: ["edit","destroy"], title: "&nbsp;", width: "160px" }
], //columns的field對應到customer資料表的欄位
sortable: true,
pageable: true,
filterable: true,
width: 800,
toolbar: ["create"],
editable: {
mode: "popup", //使用Popup的模式編輯資料
update: true, // 若設定為True,當按下Update才server資料
}
});
});
</script>
}
<div id="gridData"></div>


延伸閱讀




2013年12月25日 星期三

KendoUI & ASP.NET MVC系列文章 - 處理CRUD-使用Ajax讀取後端Model資料

前言

前兩篇為KendoUI基本的介紹,而此篇將會使用ASP.NET MVC來實做Ajax讀取資料。以下是本範例的環境:

Visual Studio 2013

ASP.NET MVC 5

Entity Framwork 6.0.2

北風資料庫(localdb)

以上逐一解釋就太佔篇幅了,將會整理一些學習資源於延伸閱讀裡

加入MVC的M (Model)

雖然新增一個MVC專案,就會將Model、View、Contoller三個資料夾拆分好,但實務上,因為Model通常會因為有複雜的關聯表或商業邏輯,所以通常即使是小專案,我還是會將Model變成是一個獨立的專案來處理。

在方案檔點選右鍵→新增專案

image

新增一個KendoUI.Model類別庫

image

在KendoUI.Model專案點右鍵,加入新項目,選擇ADO.NET實體資料模型

image

選擇從資料庫產生(這就是所謂的database first開發方式),而至於北風資料庫如何加到localDB,這邊就不多介紹了

image

選擇建立連線,輸入(localdb)\v11.0,並選擇已建好的資料庫

image

接著加入Customers資料表,本例將已此做Demo

image

接著我們回到Web專案,點選右鍵→加入參考,選擇我們的Model專案,接著整個方案Build一下,讓Web專案看得懂Model專案的class

image

加入MVC的C (Controller )

加入Contoller部分上一篇已經介紹過,而不同的是這次我們選擇自動新增view和基本的Entity Framework model

image

依照下圖,命名為GridAjax,資料來源為北風資料庫的Customers,還有載入上一篇所建置的layout(主要載入一些JQuery和KendoUI函式庫)

image 

新增完後會發現MVC已經幫我們建置好很陽春的Grid了

image 

而我們不需要用此陽春的Gird,再來就是將KendoUI Grid套用進去,我們先回到View,將內建產生的程式碼由以下程式碼替代,KendoUI Grid 的設置方式都不再多說,要注意的是,我們資料來源不再是像前一篇載入一個.js檔,而是用Ajax跟後端要資料。

@model IEnumerable<KendoUI.Model.Customers>

@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/BaseLayoutPage.cshtml";
}

@section scripts
{
<script type="text/javascript">
$(function () {
//資料來源物件改用Ajax
var dataSrc = new kendo.data.DataSource({
transport: {
read: {
type: "POST",
url: "/GridAjax/GetCustomer",
dataType: "json"
}
},
pageSize: 20,
serverPaging: true,
serverSorting: true
});

$("#gridData").kendoGrid({
dataSource: dataSrc,
columns: [
{ field: "CustomerID", title: "CustomerID" },
{ field: "CompanyName", title: "CompanyName" },
{ field: "ContactName", title: "ContactName" },
{ field: "City", title: "City" },
], //columns的field對應到customer資料表的欄位
sortable: true,
pageable: true,
filterable: true,
width: '800'
});
});
</script>
}
<div id="gridData"></div>

接著回到Contoller,預設是載入Index時就將Customers資料抓回來


image


但我們希望Grid是用Ajax的方式載入,故做以下小修改,先新增一個接收Ajax的function

private NorthwindEntities db = new NorthwindEntities();

// GET: /GridAjax/
public ActionResult Index()
{
return View();
}

public JsonResult GetCustomer()
{
var customers = db.Customers.ToList();
return Json(customers, JsonRequestBehavior.AllowGet);

}

這樣就很輕鬆的完成Gird繫結資料,但會發現這樣並沒有分頁的功能,所以我們接下來要實做


image


開啟偵錯模式,我們會發現POST過來的資料已有一些分頁的參數(take、skip、page、pagesize、sort),我們可以利用這些參數去進去分頁篩選或排序


image


但是其實不用這麼麻煩…有高手幫我們把這些事情都處理掉了!


首先再方案檔點右鍵,選擇管理Nuget套件,下載安裝KendoGridBinder


image


我們再將Contoller做以下修改,KendoGridRequest和Kendo這個類別就幫我們搞定了分頁排序等等功能

private NorthwindEntities db = new NorthwindEntities();

// GET: /GridAjax/
public ActionResult Index()
{
return View();
}

public JsonResult GetCustomer(KendoGridRequest request)
{
var result = db.Customers.ToList();
return Json(new KendoGrid<Customers>(request, result), JsonRequestBehavior.AllowGet);
}
而View我們增加以下schema的code,至於為什麼要增加此段呢?原因是因為KendoGridBinder這個套件回傳的JSON格式不太相同,他將所有資料放入一個名稱叫data的陣列,和回傳total的數字欄位
    var dataSrc = new kendo.data.DataSource({
transport: {
read: {
type: "POST",
url: "/GridAjax/GetCustomer",
dataType: "json"
}
},
schema: {
data: function (d) {
return d.data;
},
total: function (d) { return d.total; }
},
pageSize: 20,
serverPaging: true,
serverSorting: true
});

image


這樣就輕鬆完成一個多功能的Grid啦!!來看看執行結果吧


1.gif


後記


本篇會有點攏長,但希望用逐步的方式讓初學者能照步驟實做出來,如果對MVC已經相當熟悉的建議可以看黑暗大-在ASP.NET MVC 4中使用Kendo UI Grid 的文章,非常的簡潔明瞭!!


再來的幾篇我們將繼續完成新增、編輯、刪除功能!


延伸閱讀


如果對上列技術不太熟的,建議可以看看這些很棒的文章

mrkt 的程式學習筆記 - ASP.NET MVC 分層架構系列文
天空的垃圾場 – ASP.NET MVC系列文
[下載] 範例資料庫(含中文Northwind資料庫)
LocalDB:微软的新生代轻量级数据库-CSDN.NET
ASP.NET MVC 4 與 jqGrid 入門實作
Kendo UI API Reference

2013年12月23日 星期一

KendoUI & ASP.NET MVC系列文章 - 基本的Grid功能

前言

在上一篇我們介紹了開發KendoUI相關的準備工作後,這篇將會介紹網頁開發上最為常見的Grid功能,而此篇的目的希望使用MVC的View,來介紹KendoUI Grid的幾個好用功能。

建立MVC的View (如已熟悉可跳過此區塊)

在ASP.NET Webform我們有Master Page的頁面,用來放一些共用的Html(如header或footer),及一些共用的.js、.css檔,而在ASP.NET MVC我們所使用的為Layout Page,找到View裡面的Shared資料夾,點選右鍵加入新項目,選擇Layout Page並修改名稱為BaseLayoutPage.cshtml

image

接下來我們在這個共用的Layout載入KendoUI,載入的檔案在上一篇已經提過,而RenderSection可以把他想成是我們"挖的洞",如我新增了一個scripts的洞,目的就是讓使用此Layout的頁面,能在這個洞坑裡面寫一些JavaScript。

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/kendo/2013.3.1119/kendo.common.min.css")
@Styles.Render("~/Content/kendo/2013.3.1119/kendo.bootstrap.min.css")
@Scripts.Render("~/Scripts/jquery-1.10.2.min.js")
@Scripts.Render("~/Scripts/kendo/2013.3.1119/kendo.web.min.js")
@RenderSection("scripts", required: false)
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>


接著我們到Controller資料夾,點選加入控制器,新增一個空白的Controller,此例命名為BaseController


image


將ActionResult重新命名為BaseGrid,點選新增檢視


image


Layout Page記得選擇我們剛剛建的BaseLayoutPage.cshtml


image


如此我們就建立了一個View了,下個段落將開始實做KendoUI的Grid!


image


建立KendoUI Grid的資料繫結


此篇重點會在介紹Grid的基本功能及屬性,故不會使用到MVC的Model,故我會載入一個.js檔來當資料來源


而打開這個.js檔,主要就是定義一個products的物件

var products = [{
ProductID: 1,
ProductName: "Chai",
SupplierID: 1,
CategoryID: 1,
QuantityPerUnit: "10 boxes x 20 bags",
UnitPrice: 18.0000,
UnitsInStock: 39,
UnitsOnOrder: 0,
ReorderLevel: 10,
Discontinued: false,
Category: {
CategoryID: 1,
CategoryName: "Beverages",
Description: "Soft drinks, coffees, teas, beers, and ales"
}
}

接著我們在html新增一個div標籤,ID命名為gridData

<div id="gridData"></div>

接著在剛剛挖的scripts區塊加入以下程式碼,就可以完成Grid的資料繫結了,對我來講,這些程式碼的功能和屬性設置方式並不會很難懂,故上手其實蠻容易的,且對於欄位的設定,還能針對價錢做格式的轉換,不用在程式另外處理。

@section scripts
{
<script src="~/Scripts/products.js"></script>
<script type="text/javascript">
$(function () {
//建立資料來源
var dataSrc = new kendo.data.DataSource({
data: products, //指定products.js的products陣列
schema: {
model: {
fields: {
ProductName: { type: "string" },
UnitPrice: { type: "number" },
UnitsInStock: { type: "number" },
Discontinued: { type: "boolean" }
}
}
},
pageSize: 20 //每筆顯示頁數設定為20
});

$("#gridData").kendoGrid({
//Grid的屬性及功能設置都可加在以下程式區塊
dataSource: dataSrc,
height: 500,
pageable: {
input: true,
numeric: false
},//分頁導覽顯示
columns: [
"ProductName",
{ field: "UnitPrice", title: "Unit Price", format: "{0:c}", width: "130px" },
{ field: "UnitsInStock", title: "Units In Stock", width: "130px" },
{ field: "Discontinued", width: "130px" }
]
});
});
</script>
}

image


KendoUI Grid功能介紹


KendoUI Grid提供的功能非常多,以下介紹幾個我覺得不錯的功能,會發現以往要另外寫程式處理的功能,現在只要指定一個屬性就可完成了 lol


詳細可搭配此API文件的Configuration去設定http://docs.kendoui.com/api/web/grid

filterable: true (欄位篩選)
image 
sortable: true (欄位排序)
image 
selectable: true (選取某列)
image 


resizable: true (欄位寬度拖曳)

groupable: true (欄位群組分類)
image 

其他小技巧


Grid在很多頁面都會使用到時,不仿將基本的設置移至VS的工具箱,下次使用時直接拖拉即可


1


後記


這兩篇我們都沒寫到什麼程式  囧 !! 主要都在KendoUI Grid的基本功能,而再來的幾篇,我們將會實做搭配後端Model做為資料來源,漸漸的完成實務上碰到的情況。


參考資料


http://demos.kendoui.com/web/overview/index.html

2013年12月22日 星期日

KendoUI & ASP.NET MVC系列文章 - 在Visual Studio安裝及更換主題

前言

此篇主要介紹在Visual Studio如何用Nuget安裝KendUI Freamwork及如何更換主題

下載與安裝

在專案上點右鍵,選擇管理Nuget套件

image

選擇線上分類,輸入kendoui,點選安裝

image

安裝完後,在MVC的專案,content(.css)和Scripts(.js)資料夾會多出Kendo資料夾,底下會有版號的資料夾名稱

image

載入方式

如果是純html,可以在<head></head>標籤內載入以下檔案

image

接著我們在html新增一個input標籤,實做KendoUI的日期選擇器

image

並加入以下JavaScript

image

這樣就完成基本的日期選擇器了

image

更換主題

KendoUI有另一個很吸引我的另一點是他有非常多的主題可以更換,且每個主題配色都蠻舒服的

image (圖片截取自官網)

而我們要切換主題,其實只要載入不同的css即可

image

如此就變成bootstrap主題了!

image

自訂主題

如果提供的主題與系統配色不合,對自己配色有信心,KendoUI也有提供很方便的Theme Builders,可以客製化你的主題檔

image

調整完後可以點選Get CSS,將所有程式碼貼回你的.css檔(建議是另外新增一個.css)

image

讓Visual Studio看懂KendoUI intellisense

如果不是用Nuget,而是用手動加入.css或.js的方式,可能Visual Studio不會有Intellisense(智慧提示功能)

image

解決方式是打開Scripts底下的_references.js檔案,將KendoUI Scripts路徑參考進去

image

後續

此篇主要簡單介紹開發前的準備,接下來幾篇文章,主要針對最常用的Grid來介紹!