顯示具有 Telerik 標籤的文章。 顯示所有文章
顯示具有 Telerik 標籤的文章。 顯示所有文章

How to select dropdown list item by text

在網頁上實作""修改現有資料""時,一般要讓Dropdownlist選中本來的值,大多有以下二種作法
1. 在後端組資料時就賦予哪一個是Selected="true"
2. 用jQuery讓符合指定value的選項被選中
    寫法為 $("#Dropdownlist的ID").val("指定的值");

在Telerik Grid中也是採用第二種作法
function Grid_onEdit(e) {
    var dataItem = e.dataItem;
    var mode = e.mode;
    var form = e.form;
    var priceTextBox = $(form).find("#Price");

    var customerDropDownList = $(form).find("#Customer");
    if (mode == "edit") {
        //Select the proper dropdown list item
        customerDropDownList.val(dataItem.CustomerID);
    }
}

但是,當Dropdownlist的Text和Value不同時,
customerDropDownList.val(dataItem.CustomerID); 寫法是無效且不合理的
因為dataItem.CustomerID取回的是Dropdownlist的Text,但jQuery的val是用來比對Value

解決的寫法如下
$("select option:contains(" + dataItem.CustomerID+ ")").attr('selected', true); 

Telerik Grid Custom Binding by TelerikMvcGridCustomBindingHelper


Telerik Grid可設置.Sortable()、.Pageable()、.Groupable()、.Filterable()達到排序、分頁、分群、過濾資料的效果,但這是使用Telerik所提供的binding為前提。

若採用CustomBinding,以上效果(排序、分頁、分群、過濾)全部都要自行實作,實作方式請參考官網CustomBinding,或是直接下載官方論壇提供的範例


依官方解法,每次CustomBinding都要針對Binding的資料結構各實作paging、sorting、grouping一次,尤其grouping更要事先設計好針對那些欄位是可以排序的。
若覺得官方解法太麻煩~~是真的很麻煩ε(┬┬_┬┬)3 ,或是資料結構過於複雜無法呈現,或你跟我一樣懶惰XDD
建議可搭配另一套件TelerikMvcGridCustomBindingHelper,達到更彈性、修改更少的寫法!

承接前篇文章Telerik Grid Custom Binding,BL與View都不用做任何改變,針對Controller所需異動描述如下

1. 至CodePlex下載TelerikMvcGridCustomBindingHelper套件
解壓或用NuGet安裝裡面二支library
download:http://tgh.codeplex.com/
library:TelerikMvcGridCustomBindingHelper.dll、TelerikMvcGridCustomBindingHelper.NHibernate.dll
version:1.10.15.247
notice:Telerik要記得更新到2012 Q2

2. 加入AutoMapper參考
download link:使用NuGet下指令安裝,指令為PM> Install-Package AutoMapper 
version:2.1.267.0

3. 把Helper要用到的另二種library下載回來參考
download:http://nhforge.org/Default.aspx
library:NHibernate.dll、Iesi.Collections.dll
version:3.3.1.4000

4. 修改Controller寫法
[GridAction(EnableCustomBinding = true)]
public ActionResult ListPO_CustomBinding(GridCommand command)
{
int totalCount = POService.QueryPOListIndex(command);
ViewBag.POTotalCount = totalCount;
List<PO> data = POService.QueryPOList(command);

//使用TelerikMvcGridCustomBindingHelper
for (int i = 0; i < (command.Page - 1) * command.PageSize; i++)
{
PO dd = new PO();
data.Insert(0, dd);
}
IQueryable<PO>
query = data.AsQueryable();
var gridHelper = new GridCustomBindingHelper<PO, PO>(command, query);
var gridModel = gridHelper.BuildGridModel();
gridModel.Total = ViewBag.POTotalCount;
return View(gridModel);

}


仔細比較與前篇寫法的差異處(黃色highlight),只要修改Controller一點點就省去實作N遍的paging、sorting、grouping
真是太感謝TelerikMvcGridCustomBindingHelper的開發團隊╭ (′▽`)╭(′▽`)╭(′▽`)╯

Telerik Grid Custom Binding

Telerik Grid算是做得很完善,API也多~但客製化需求還是在所難免。
比如有個表單系統只提供最簡單的資料瀏覽,姑且不論是否下查詢條件,要是資料百萬筆豈不是起肖?!

較好的做法是用分頁區別之餘,但每次只取該分頁的資料,而不是一次取回百萬筆資料再作分頁

本文就要來介紹,如何實作Custom Binding

1. 計算總筆數(因為是CustomBinding,GridModel需要的總筆數必須自己計算)
public int QueryPOListIndex(GridCommand command)
{
var entity = mydata.PO.AsQueryable();
int ttlCount = entity.ToList().Count();
return ttlCount;
}


2. 像平常一樣取資料(請依照自己的需求和資料作變化)
public List<PO> QueryPOList(GridCommand command)
{
var entity = mydata.PO.AsQueryable();
//Sorting(必須有Default的Order By條件,否則會Error)
entity = entity.OrderBy(order => order.PONo);
//Then paging
if (command.PageSize > 0)
entity = entity.Skip((command.Page - 1) * command.PageSize);
entity = entity.Take(command.PageSize);
return entity.ToList();
}


前面二項為Bussiness Layer(POService),若專案架構較小~亦可將其寫在Controller中
3. Controller
//須注意的是, ViewBag.DataTotalCount在此頁載入時須先給予一預設值(ex:0),之後的查詢function再賦予正確值
public ActionResult ListPO()
{
ViewBag.POTotalCount = 0;
return View();
}

[GridAction(EnableCustomBinding = true)]
public ActionResult ListPO_CustomBinding(GridCommand command)
{
int totalCount = POService.QueryPOListIndex(command);
ViewBag.POTotalCount = totalCount;
List<POt> data = POService.QueryPOList(command);
return View(new GridModel
{
Data = data,
Total = totalCount
});
}


4. View
@(Html.Telerik().Grid<PO>()
.Name("Grid")
.Columns(columns => {
columns.Bound(c => c.PONo);
columns.Bound(c => c.DocDate);
columns.Bound(c => c.Company);
columns.Bound(c => c.Vendor);
columns.Bound(c => c.Status);
columns.Bound(c => c.CmpltReceived);
})
.Pageable(settings => settings.Total((int)ViewBag.POTotalCount))
.DataBinding(dataBinding => dataBinding.Ajax().Select("ListPO_CustomBinding", "Inbound"))
.EnableCustomBinding(true)

.Sortable()
.Groupable()
)

Kendo UI誕生

Telerik前陣子放出消息,表示支援Telerik Extensions for ASP.NET MVC只到明年(2013 Q3),
而最大更新差不多就停留在目前的2012 Q2,之後版本多是修正bug和提升performance

取而代之的是這套Kendo UI Complete for ASP.NET MVC,今年7月已推出正式版,
簡單來說就是Kendo UI=CSS 3 + Html 5 + Javascript,以現階段版本還比不上Telerik的完善,開發文件也不盡完全,還不用急著升級
但未來若要朝MVC 4升級,可能要考慮轉用這套(Telerik Extensions for ASP.NET MVC只支援到MVC 3),另外Kendo對REST也提供比較好的支援,以微軟將推出的.Net Framework 4.5來看也是有此趨勢。

其他參考資訊
官方對一些疑慮的釐清
從Telerik升級到Kendo
Kendo UI Complete for ASP.NET MVC

Telerik Grid ─ Pass additional values from clientside events


Telerik GridDelete只要有unique value作為識別,就可以取得特定資料,進行刪除的動作。
unique可藉設定DataKeys達到,例如
    .DataKeys(datakeys =>
    {
        datakeys.Add(o => o.Id).RouteKey("KeyId");
        datakeys.Add(o => o.Name).RouteKey("KeyName");
    })

但有時會希望刪除後要做些額外處理,總不能設NRouteKey吧(也不是不對,蠻爛的就是….

依據Telerik論壇的資訊,可以傳遞額外的資訊,參考網址如下

若額外資訊不只一組,使用論壇建議的方法~直接用JSON包,傳值還是有問題,經過本人測試,只要一個一個指定就OK!程式碼如下
JavaScript function Grid_OnDelete(e) {
    e.values.A= $('#myA').val();
    e.values.B= $('#myB').val();
}

C#
[GridAction]
public ActionResult _AjaxDelete(string KeyId,string A, string B)
{   //略
}

最後附上完整的UI
@(Html.Telerik().Grid()
    .Name("Grid")
    .DataKeys(datakeys =>
    {
        datakeys.Add(o => o.Id).RouteKey("KeyId");
        datakeys.Add(o => o.GroupName).RouteKey("KeyGroupName");
    })
    .ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Text).ImageHtmlAttributes(new { style = "margin-left:0" }))
    .Columns(columns =>
    {
        columns.Bound(o => o.GroupName);
        columns.Bound(o => o.Description);
        columns.Bound(o => o.CloudGroup);
        columns.Bound(o => o.SocialGroup);
        columns.Command(commands =>
        {
            commands.Edit().ButtonType(GridButtonType.Text);
            commands.Delete().ButtonType(GridButtonType.Text);
        });
    })
    .DataBinding(d => d.Ajax().Select("_AjaxBinding", "Partner")
        .Insert("_AjaxInsert", "Partner")
        .Update("_AjaxUpdate", "Partner")
        .Delete("_AjaxDelete", "Partner"))
    .ClientEvents(c => c.OnDelete("Grid_OnDelete"))
)

補充:不只Delete能傳遞額外資訊,Update亦可,只是要寫在OnSave event,範例如下
JavaScript
    function Grid_OnSave(e) {
        if (e.mode == 'edit') {
            e.values.A= $('#myA').val();
            e.values.B= $('#myB').val();
        }
    }

checkboxes in Telerik Grid


傳遞Telerik Grid中勾選(checkbox)的資料改良官網sample綁定單一欄位的不足,本文再針對傳遞多參數提供進階範例。

承前例,照理第二、三。。。N個參數這樣給就好
AddPartners(string[] checkedRecords, string 第二個參數, string 第三個參數)
結構一旦變成這樣,原始的checkedRecords就再也傳不過來,永遠都是null    >__<
後來發現有位老兄也遭遇相同窘境,結果Telerik論壇也沒人回=__=

後來,我改變傳遞string[]的作法,全部都用可愛的JSON來處理!!!作法如下

UI(與前文同,無須變更)
@(Html.Telerik().Grid()
.Name("Grid")
.Columns(columns => {
columns.Bound(o => o.CompanyId).ClientTemplate("< input type ='checkbox' name='checkedRecords' value='<#=CompanyId #>;<#=Name #>' / > ");
columns.Bound(o => o.Name);
columns.Bound(o => o.EnglishName);
columns.Bound(o => o.Phone);
})
.DataBinding(d => d.Ajax().Select("AjaxBinding", "Partner"))
.Pageable()
)
//按下btnAdd後要將勾選的資料傳遞到後端
< input type="button" name="btnAdd" id="btnAdd" value="Add Partner" class = "t-button" / >


JavaScript
$(document).ready(function () {
$('#btnAdd').click(function () {
var $checkedRecords = $('input[name="checkedRecords"]:checked');
if ($checkedRecords.length < 1) {
alert('你沒有選擇任何資料列!');
return;
}

var id1 = $('#myHiddenInput').val();
var id2 = $('#myDropdownList :selected').val();

//取得勾選的checkbox
var arrayChecked = new Array();
$('input[name="checkedRecords"]:checked').each(function () {
arrayChecked.push($(this).val());
});
//送出前轉換成JSON格式
var jsonChecked = JSON.stringify(arrayChecked);

$.post('AddPartners', { jsonChecked: jsonChecked, id1: id1, id2: id2 },
function(Data) {
alert(Data.Message);
}, 'json');
});
});


C#
public ActionResult AddPartners(string jsonChecked, string id1, string id2)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
string[] checkedRecords;
checkedRecords = jss.Deserialize(jsonChecked);
try
{
for (int i = 0; i < checkedRecords.Length; i++)
{
string[] Values = checkedRecords[i].Split(';');
string aa = Values[0];
string bb = Values[1];
//aa 和 bb就是前面組合的CompanyId和Name,接下來就可以繼續做其他運算
}
return new JsonResult { Data = new { Flag = "Y", Message = "OK!" } };
}
catch (Exception ex)
{
return new JsonResult { Data = new { Flag = "N", Message = ex.Message } };
}
}

Telerik Grid的水平捲軸

Telerik Grid資料過多時除分頁設定.Pageable(),還可使用.Scrollable()讓Grid有捲軸可拉動,一般只有垂直方向出現捲軸,那是因為Column寬度沒設定!
若水平方向也要有捲軸必須把所有Column寬度都設定好,否則Telerik會自動以最佳寬度去排列資料,造成資料行無限長~~版面破碎的情況。

設定範例如下
@(Html.Telerik().Grid< mydocument>()
.Name("Grid")
.Columns(columns => {
columns.Bound(o => o.UserName).Width(100);
columns.Bound(o => o.UserId).Width(200);
columns.Bound(o => o.Address).Width(100);
})
.DataBinding(d => d.Ajax().Select("_AjaxBinding", "Home"))
.Scrollable())

參考出處
網址:MVC Grid Horizontal Scrolling
資訊:Horizontal scrolling is enabled automatically in case the total width of the columns exceeds the width of the grid  and the Scrollable method is invoked. Make sure you have specified the width of your columns though.

Telerik Grid之OnSave event

OnSave event的撰寫大概不脫下列模式
< script type="text/javascript">
function Grid_onSave(e) {
var dataItem = e.dataItem;
var values = e.values;
var form = e.form;
//event handling code
}

又MVC中常使用強型別,傳遞整個Model作資料更新,如果你的頁面僅止於最簡單的Model傳遞,那麼OnSave enevt一般是極少用到。

但總是有些情況需要新舊值比對(驗證等等),那麼就要仔細注意e.dataItem與e.values的差別!
e.dataItem  →  舊的值(本來的資訊~存在DB的)
e.values       →  新的值(使用者keyin~準備更新的新資訊)

當然二者都是值的集合,若要取單一值,直接指定欄位名稱即可。假設有個自定義Model如下
public class UserInfo{
public string UserName { get; set; }
public string UserId { get; set; }
public string Company { get; set; }
}

如果要取UserName的新舊值
var oldUser = e.dataItem.UserName; //舊的值
var newUser = e.values.UserName; //新的值

傳遞Telerik Grid中勾選(checkbox)的資料

Telerik Grid透過client-side templates去擺放checkbox,可讓使用者勾選資料以進一步傳遞多選的資料列,範例網址grid_checkbox_ajax
該範例只綁定單一欄位(欄位類型Int),本文示範前端如何綁定多個欄位,以及後端接收後的重組方式

UI
@(Html.Telerik().Grid()
.Name("Grid")
.Columns(columns => {
columns.Bound(o => o.CompanyId).ClientTemplate("< input type ='checkbox' name='checkedRecords' value='<#=CompanyId #>;<#=Name #>' / > ");
columns.Bound(o => o.Name);
columns.Bound(o => o.EnglishName);
columns.Bound(o => o.Phone);
})
.DataBinding(d => d.Ajax().Select("AjaxBinding", "Partner"))
.Pageable()
)
//按下btnAdd後要將勾選的資料傳遞到後端
< input type="button" name="btnAdd" id="btnAdd" value="Add Partner" class = "t-button" / >


Javascript
$(document).ready(function () {
$('#btnAdd').click(function () {
var $checkedRecords = $(':checked');
//先確認使用者是否沒有勾選任何資料
if ($checkedRecords.length < 1) {
alert('你沒有選擇任何資料列 !');
return;
}
//把勾選的資料傳到後端
$.post('AddPartners', $checkedRecords,
function (Data){
alert(Data.Message);
}, 'json');
});
});


C#
[HttpPost]
public ActionResult AddPartners(string[] checkedRecords)
{
try
{
for (int i = 0; i < checkedRecords.Length; i++)
{
string[] Values = checkedRecords[i].Split(';');
string aa = Values[0] ;
string bb = Values[1] ;
//aa 和 bb就是前面組合的CompanyId和Name,接下來就可以繼續做其他運算
}
return new JsonResult { Data = new { Flag = "Y", Message = "OK !" } };
}
catch (Exception ex)
{
return new JsonResult { Data = new { Flag = "N", Message = ex.Message } };
}
}

隱藏Telerik Grid之更新按鈕

使用Telerik Grid for MVC除非有極特殊需求,一般還是建議採官方提供的用法,不然前後端有時候都要自己多做工還蠻麻煩的XD

Grid在資料編輯方面有Insert、Update、Delete、BatchEditing
最近做的專案需要Insert & Delete(本文不討論Batch)但又不允許使用者Update,可是Update按鈕和Insert按鈕是同一個!!!  請看下列連環圖說明

預設編輯畫面(可以Insert、Update、Delete)
上方的"Add new record"按鈕可插入一筆新資料,右側的"Commands"欄位有"Edit"和"Delete"按鈕,但Edit按鈕身兼二職~請續看連環圖
圖一

click圖一的Edit按鈕後,該列資料會開啟編輯狀態(例如label變成可輸入的input),本來的Edit按鈕也因編輯狀態而變成"Update"按鈕
圖二

click圖一的Add new record按鈕後,會新增一筆空白資料列,本來的Edit按鈕因新增變成"Insert"按鈕
圖三

簡單來說,就是我不希望有圖二的狀態出現,但又想使用Telerik提供的event去完成Insert & Delete。最快(偷懶)的方式就是把圖一Edit按鈕隱藏,實作方式如下

1.在Grid加入ClientEvent
.ClientEvents(c => c.OnDataBound("Grid_OnDataBound"))

2.撰寫Grid_OnDataBound事件
function Grid_OnDataBound(e) {
$("a:contains('Edit')").hide();
}

此寫法只會將< a>中有Edit的部分隱藏,不影響Add new record要用的Insert按鈕,請安心使用 0.<

Telerik Extensions for ASP .NET MVC(Version Q1 2012)

之前寫過詳細的Telerik Extensions for ASP .NET MVC服用文,針對舊文的第二點"web.config加入下列設定"更新一下資訊。

Telerik已經將繁複的設定改為一行解決,以我目前使用的版本(Q1 2012)為例,只要在web.config加上此行即可使用,其餘都不用再多寫!!!
<add namespace="Telerik.Web.Mvc.UI" />

官方說明網頁在這http://www.telerik.com/help/aspnet-mvc/getting-started-using-telerik-extensions-for-asp.net-mvc-in-your-project.html

Telerik Grid for ASP .NET MVC基本設定

前文準備好開發環境,開始使用Telerik最威的Grid componment

顧及資料龐大與server端,我們採用AJAX作為databinding的方式,而Telerik Grid若只作查詢只要撰寫databinding用的func.即可。一個樣式豐富又基本的Grid設定如下
<%= Html.Telerik().Grid < TelerikDemo.Models.Model1 >() .Name("Grid") //Column設定 .Columns(columns => { //隱藏欄位 columns.Bound(u => u.Id).Hidden(true); //欄位寬度 columns.Bound(u => u.Name).Width(120); //欄位表頭 columns.Bound(u => u.Age).Title("年齡"); //欄位格式 columns.Bound(u => u.Birth).Format("{0:yyyy/MM/dd}"); //欄位以其他控制項呈現 columns.Bound(u => u.Status) .ClientTemplate("< select > < option value='< #= Status # >' selected='selected' >< #= Status # >< /option >< /select >"); //欄位樣式(直接設定) columns.Bound(u => u.Tel). HtmlAttributes(new { style = "color: green" }); }) //資料繫結Select(actionName, controllerName) .DataBinding(dataBinding => dataBinding.Ajax().Select("_BindingModel1", "Grid")) //頁籤設定 .Pageable(paging => paging.PageTo(3)//初載時顯示第幾頁 .Position(GridPagerPosition.Both)//分頁的位置 //提供多個PageSize讓用戶彈性更改一頁呈現幾筆資料,而決定PageSize的控制項是PageSizeDropDown .PageSize(10, new int[] { 5, 10, 20 }) //PageInput讓使用者以keyin方式直接跳到想要的page ; //NextPreviousAndNumeric表示同時提供上/下一頁與數字頁的功能 ; //PageSizeDropDown提供下拉式選單更改每頁的筆數 .Style(GridPagerStyles.PageInput | GridPagerStyles.NextPreviousAndNumeric | GridPagerStyles.PageSizeDropDown)) //排序設定 .Sortable(sorting => sorting.OrderBy(order => order.Add(u => u.Name))) //表格scrollbar .Scrollable() //資料分組 .Groupable() //資料過濾 .Filterable() .Selectable() .ClientEvents(e => e.OnRowSelect("onRowSelected")) %>


至此,在GridController寫個名為_BindingModel1的func.負責取回可於Telerik Grid顯示的資料,Grid就可執行無誤。
另外,最後的onRowSelected則是撰寫於前端的js function,主要是在觸發client端的row on select時告訴Grid要執行的事情,非必要項~~依專案需求與否再加即可。

Telerik Extensions for ASP .NET MVC

MVC有點黏又不太黏的關係,讓前端開發相較傳統ASP .NET有點點不順手,尤其"查詢"一直佔系統的大宗,如何將大量複雜的資料以優美介面呈現予用戶就顯得非常重要!

網路上不少佛心來的第三方控件,本文將介紹TELERIK公司開發的Telerik Extensions for ASP.NET MVC(以下簡稱Telerik)

和其他open source一樣可使用MSI檔auto install或自解壓縮檔至對應路徑,本人懶惰就直接使用MSI搞定,但若有特殊版本需求請自行上網download解壓。

另外要特別注意Telerik支援的MVC版本,以本文2011 Q2(2011/7/12 release)為例支援MVC 1、2、3,但並非""同時支援""多重版本,不同版本請refrence相應的Telerik.Web.Mvc.dll
Telerik安裝完畢在C:\Program Files的檔案架構

VS2010多了專屬Telerik的Project Template

若專案規模不大,又懶得手動設定所需的相關檔案,可參照上圖選用Telerik MVC 3 Web Application,毋須額外設定即可著手撰寫專案 0 . <


話說回來,採用MVC開發的系統都不小,要如何在團隊規劃的架構下順順使用Telerik呢?
假設Telerik安裝完畢且MVC開發環境也備齊,使用方式如下 :

1. 於MVC的WEB專案參考Telerik.Web.Mvc.dll(注意MVC版本)

2. web.config加入下列設定
<add namespace="Telerik.Web.Mvc.UI"/> 
<sectionGroup name="telerik"><section name="webAssets" type="Telerik.Web.Mvc.Configuration.WebAssetConfigurationSection, Telerik.Web.Mvc" requirePermission="false" /><sectionGroup>
<add name="asset" preCondition="integratedMode" verb="GET,HEAD" path="asset.axd" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc" /> 
<telerik<webAssets useTelerikContentDeliveryNetwork="true" /> telerik> 
新版(Version Q1 2012)設定請看此→Telerik Extensions for ASP .NET MVC(Version Q1 2012)


3. 加入JavaScript file並註冊
以本文使用的2011 Q2為例,在C:\Program Files\Telerik\Extensions for ASP.NET MVC Q2 2011\Scripts內附""2011.2.712""資料夾,包括Telerik所用的全數JS,請將這個以日期命名的資料夾整份複製(也就是說Scripts資料夾內有2011.2.712資料夾)到WEB專案的Scripts資料夾。

註冊位置在所有component之後與< / body>之前
<%:Html.Telerik().ScriptRegistrar().Globalization(true).DefaultGroup(g => g.Combined(true).Compress(true)) %>
4. 加入CSS file並註冊
以本文使用的2011 Q2為例,在C:\Program Files (x86)\Telerik\Extensions for ASP.NET MVC Q2 2011\Content內附""2011.2.712""資料夾,包括Telerik所用的全數CSS,請將這個以日期命名的資料夾整份複製到WEB專案的Content資料夾。

註冊位置於head tag之間
<head><%: Html.Telerik().StyleSheetRegistrar().DefaultGroup(g => g.Add("telerik.common.css").Add("telerik.vista.css").Add("telerik.rtl.css").Combined(true).Compress(true))%> < /head>

完成上述步驟就可以安心服用Telerik各類花俏component