喜帳面の日記

50歳越えおやじのASP.NET MVC への挑戦日記です。

ASP.NET MVC Razor をやってみた。 IgniteUI 編 ラッパークラスを参照してコピペでちょっとは楽できるかも

ASP.NET MVC 周辺の記事を書きたいなと思います。ここしばらくは、私が運営している [喜帳面.net]でも使ってる、お気に入りの開発ツール「IgniteUI」の周辺について [喜帳面.net]での事例などを織り交ぜながら、メモを残しておきます。

対象の環境は、ASP.NET MVC4 Razor C# IgniteUIは2014 Volume 2 です。ちょっと古いけどあしからず。


さて今回は、へんてこなタイトルになってしまいましたが、MVCのRazorを使って「IgniteUI」を利用する場合、「このオプションを使いたいけど、どう書けばいいの?引数の指定の仕方が???」ってときに使ってる方法についてメモを残しておきます。

 

今回の私の事例は、「igCombo」で「リスト内の複数項目をチェックボックスを使って選択する」ってRazorではどう記述するんだっけ? です。

f:id:SannomiyaNotes:20150821112354p:plain

上記のようにigComboでは、複数の項目の選択、またチェックボックスの使用が可能です。この部分Razorのcshtmlでは以下のかんじで記述すればOKです。(Vol 2014.2では)

@(Html.Infragistics().ComboFor(m => m.BumonCDs).ID("cmbBumonCDs")
    	.MultiSelection(ComboMultiSelection.OnWithCheckboxes) 
    	.DataSourceUrl(Url.Action("GetComboListBumonCD"))
    	.ValueKey("BumonCD").TextKey("BumonName")
    	.DataBind().Render()
  	)

複数選択を指定している部分は2行目の

.MultiSelection(ComboMultiSelection.OnWithCheckboxes) 

 ここなのですが、help(Vol 2014.2)を見ると

f:id:SannomiyaNotes:20150821114455p:plain

MultiSelectionとOnWithCheckboxesといったキーワードがわかります。

そこで、インテリセンスをつかって [.] と入力し候補から[ .MultiSelection]を選択するところまでは簡単に行けます。次の引数部の指定で[(]を入力すると「ComboMultiSelection? enable」ってヒントが表示されるので、「ComboMultiSelection」って入力していけばいいのですが、ちょっと長くて面倒ですね。

そんな時は、「MultiSelection」をダブルクリックで選択して右クリック「定義へ移動」を選択すると、「 ComboWrapper」クラスの該当するメンバーが表示されます。そこからコピー&ペーストします。今回の例だと「ComboMultiSelection」をコピー&ペーストして、次の.OnWithCheckboxesは [.]を打てば、候補リストが表示されるのでそこから選択すれば出来上がりです。

こんな感じで、Wrapperクラスを見ていくと、helpでは見落としてしまっていた機能を発見できたりもして得することもありますね。

今回は以上です。

 

igCombo Vol 15で幾つか機能改定があったみたいですね。helpみるとMultiSelectionの部分に相違があります。ちょっと気になったので取り急ぎご報告。

Vol14.2  http://help.infragistics.com/jQuery/2014.2/ui.igcombo 

Vol15.1  http://help.infragistics.com/jQuery/2015.1/ui.igcombo

 

ASP.NET MVC Razor をやってみた。 IgniteUI 編 その4 igGridのGridUpdating機能について

ASP.NET MVC 周辺の記事を書きたいなと思います。ここしばらくは、私が運営している [喜帳面.net]で使ってる [IgniteUI]の周辺について [喜帳面.net]での事例などを織り交ぜながら、メモを残しています。

対象の環境は、ASP.NET MVC4 Razor C# IgniteUIは2013 Volume 2 です。ちょっと古いけどあしからず。

IGNITEUIのヘルプ類はこちらの  [ページ]jQuery/HTML5部分を参照ください。


今回は、igGridの更新機能(igGridUpdating )についてメモしておきます。

1.トランザクションを利用したバッチ更新処理について

igGridの更新機能を使用するとgridのデータの追加・更新・削除を行うことができます。

gridのデータ操作内容はクライアントのトランザクションに格納されます。トランザクションを「rollback」することで操作の取り消しも可能です。

クライアントでigGridのsaveChangesメソッドを呼び出すと、igGridのUpdateUrlで指定したURLにトランザクションがpostされます。

サーバー側では、postされたデータを、GridModel.LoadTransactions(string postdata) を使用して逆シリアル化しトランザクションをリスト化、次にトランザクションの行毎のタイプ{"newrow","row","deleterow"など}を判定してデータベースへの更新処理などを行うことができます。

以上のことはこちらの [サンプル Grid基本編集] に詳しく記載されています。

トランザクションを利用するには、igGridのオプションAutoCommitがfalseになっている必要があります。デフォルトはfalseになっています。

 

2.行内編集とダイアログ編集

下記画像は、上記のサンプルをもとに見よう見まねで更新処理機能を実装した [喜帳面.net]での事例です。管理者用の処理なので、メニューには登録していません。

 grid表示時はこんな風に表示されています。

f:id:SannomiyaNotes:20150721160024p:plain

UpdatingのオプションにEditModeがあり、(GridEditMode.Cell, .None,.Row,.RowEditTemplate)から選択可能です。

.EditMode(GridEditMode.Row)と指定すると行内でのデータ編集となります。

 f:id:SannomiyaNotes:20150721160726p:plain

「新規行の追加」をクリックした場合は、「新規行の追加」と記載されている行での編集処理となります。

 

.EditMode(GridEditMode.RowEditTemplate)を指定すると、ダイアログでのデータ編集となります。「新規行の追加」をクリックした場合もダイアログで追加レコードを入力します。

f:id:SannomiyaNotes:20150721160851p:plain

行の削除は、グリッド右端に表示される「×」アイコンをクリックします。

 

1行編集(追加や変更)が完了すると、グリッド上に変更後のデータが斜体で表示されます。また、削除データは「取り消し線」が引かれます。

f:id:SannomiyaNotes:20150721163154p:plain

これらのレコードはトランザクションが保留中の状態になっています。

サンプルでは、「元に戻す」ボタンをクリックすることで、保留中のトランザクションを"rollback"し編集操作を取り消しできるようになっています。

また、"rollback"したトランザクションについては「やり直す」ボタンをクリックすることで、ロールバックしたトランザクション再反映することができるようになっています。詳細は [サンプル Grid基本編集] を参照ください。

 

3.igGridの"commit"メソッド

igGridの"commit"メソッドを実行することで保留中のトランザクションをコミットできます。コミットされると画面上では、斜体から通常のフォント表示になります。

このトランザクションのコミットはあくまでもブラウザーに保持されているトランザクションがコミットされ「ロールバック」できない状態になったということになります。この状態からgridのデータを元にもどすにはgridのソースデータを再度取得し直す必要があります。

尚、igGridのsaveChangesメソッドサーバーへpostした場合、トランザクションが保留中か否かに係らず(保留中のトランザクションも)送信されます。

 

4.igGridUpdatingの”datadirty”イベント

 ページの移動、ソート、フィルター操作を行う場合は、事前に保留中のトランザクションをコミットしておきます。保留中のトランザクションが存在すると、「JavaScript 実行時エラー: グリッドに保留中のトランザクションがあります。データのレンダリングに影響する場合があります。(以降割愛)」の例外が発生します。datadirtyイベントを使用して回避します。

//ページ移動、ソート、フィルタの実施時はグリッドに保留中のトランザクションをコミットしてfalse を返します
$(document).on("iggridupdatingdatadirty", "#grid1", function (event, ui) {
    $("#grid1").igGrid("commit");
    //saving local changes to the datasource when sorting
    return false;
});

5.EditorTypeでコンボを使用する場合

 Loaderを使用する場合、Resourcesに"igCombo"の明示が必要です。

@(Html.Infragistics().Loader()
      .ScriptPath(Url.Content("~/Scripts/IG/js/"))
      .CssPath(Url.Content("~/Content/IG/css/"))
      .Resources("igCombo") //EditorTypeでComboを使う場合明示が必要
      .Theme("metro")
      .Render()
 )

options.DataSourceUrlの使用は?? 未解決です。

今回私の事例では、EditorTypeにColumnEditorType.Comboを指定した列があります。まずデータの取得について、ComboEditorOptionsでDataSourceUrlを指定してみたのですが、ちょっとうまくない現象が発生しました。

 こんなかんじの記述です。

 

 9行目:options.DataSourceUrl(Url.Action("GetLanguageNameIDList"));

 これでコンボ用のデータを取得しようとしています。この方法でコンボのリストは表示できるのですが、レコードの内容を変更しようとコンボを開いた時点で列の値が空白になってしまいます。編集モードが行の場合、一度開くと2レコード目以降では問題なく動作します。編集モードがRowEditTemplate場合は2レコード目以降の編集でもダイアログ内の当該コンボは空白で表示されてしまいます。

憶測ですが、コンボのレコードの取得は、レコードの編集を開始した後に実行され、編集の開始時点では、リストは空状態になっており、リストに存在しない値をセットして値がnullに置き換えられているような感じがします。

DataSourceUrlを使用した対策がどうにも見つけられないので、取り急ぎ「DataSource」とViewBagを使用した [サンプル Grid基本編集]でやってる手法で対応しました。それは、

コントローラーで,iggridを含むViewをクライアントに返す際に、コンボ用のデータリストをViewBagにセットしておく。

そして、ComboEditorOptionsのデータの取得はDataSourceでそのViewBagを指定します。

18行目のDataSourceUrlをコメントアウトし、19行目でDataSource指定しています。

 

今回は以上です。

ASP.NET MVC Razor をやってみた。 IgniteUI 編 その3 igGridの列テンプレートについて

ASP.NET MVC 周辺の記事を書きたいなと思います。ここしばらくは、私が運営している [喜帳面.net]で使ってる [IgniteUI]の周辺について [喜帳面.net]での事例などを織り交ぜながら、メモを残しています。

対象の環境は、ASP.NET MVC4 RazorでIgniteUIは2013 Volume 2 です。ちょっと古いけどあしからず。


まず、以前の記事でigGridで画像を表示する方法を紹介しました。

この記事を変更させてください。 

sannomiyanotes.hatenablog.com

この記事では、rowTemplateオプションを使って画像を表示する方法を掲載したのですが、「IgniteUI 2014.1 リリースより rowTemplateオプションは非推奨」となっておりこの方法は使用できなくなりました。レスポンスアップの為らしいのですが、私の環境がまだ、2013 Volume 2のままなのは、これへの対応が完了してない為なんです。ただ今こつこつ改定中。えっと愚痴話はこの辺でやめて。

rowTemplateオプションの代替策としては、カラム個別の列テンプレートを使います。 以下はgirid内にアイコンを表示する事例で、rowTemplateオプションの使用から、ColumnsのTemplateへ記述を移動させた例です。

igGrid 2014 対策 RowTemplate-->Columns.Template


 [喜帳面.net]での[.Template]の使用事例を紹介したいと思います。

サンプルです。

iggridのTemplate使用事例

グリッド内の列を右寄せする

 サンプルソースの17、18行目を見てください。18行目の

.Template("<div align=right>${Kingaku}</div>");

 これで、[Kingaku]列が右寄せされます。

ちなみに17行目についてもふれておきますね。

.HeaderText(@rsGlobal.Kingaku)

これは、見出し部のテキスト指定です。プロジェクト内のリソースファイル[rsGlobal.resx]の名前"Kingaku"をセットしています。

事前に「@using」でリソースフォルダを指定しておきます。

例えば、@using kichoumen.Resources.Global; なかんじ。

.Format(@ViewBag.KingakuFormat)

これは金額のフォーマット指定です。事前にViewBagのKingakuFormatに "#,##0" 等をセットしています。

 尚、金額を右寄せする方法については、上記方法以外の方法として「igGrid.dataRendered イベントで各の行の TD 要素に text-align CSS ルールを適用します。」って方法が以下のサンプルに記載されています。こちらも検討ください。

jp.igniteui.com

グリッド内にアイコン等の画像を表示する

 サンプルソースの11,12行目を見てください。

column.For(x => x.Icon).HeaderText(" ").Width("32px").DataType("string")
      .Template("<IMG SRC=${Icon} style = 'width:20px;height:20px'></IMG>");//②画像の表示例

 これで、画像が表示されます。model.Iconには画像ファイルのURIを渡します。

URIは、ControllerやModel classで、UrlHelper.GenerateContentUrlメソッドを使って作成します。

例えば、

model.Icon = UrlHelper.GenerateContentUrl(contentPath, context); こんなかんじです。

 

グリッド内にアイコン等の画像を配置してクリックされたら何かする

 サンプルソースの14,15行目を見てください。

column.For(x => x.Editimg).HeaderText(@rsGlobal.Editimg).Width("30px").DataType("string")
                .Template("<input type='image' SRC=${Editimg} onclick='editgridList(${HogeId})' class='select-button' style = 'width:20px;height:20px' />");//③function呼び出し

.Templateへのセットでは、inputタグのtype属性にimageを指定し画像ボタンを作成しています。

そして、onclick='editgridList(${HogeId})' と記述することで画像がクリックされるとjavascriptの ファンクション(この例ではeditgridList)が呼び出されます。

この際、引数には当該行のPrimaryKeyである[HogeId]の値が渡されます。

[喜帳面.net]での例では、クリックされたら当該行のカラム内の値をダイアログ表示したりしてます。

当該行のカラム内の値を取得する場合は、

//gridで編集アイコンをクリックしたとき、カラムの値を取得する
function editgridList(rowId) {
    var grid = $("#Den_List").igHierarchicalGrid("rootWidget");         //rootWidget取得
    var kingaku = grid.getCellValue(rowId, "Kingaku");//getCellValueで値を取得
}

getCellValueの第一引数には、プライマリキーを渡しています。

こんなかんじでcellの値を取得することができます。


以上、igGrid列テンプレートの使用例でした。

ASP.NET MVC Razor をやってみた。 IgniteUI 編 その2 igGridのロードオンデマンドについて(2/2)

ASP.NET MVC 周辺の記事を書きたいなと思います。ここしばらくは、私が運営している [喜帳面.net]で使ってる、お気に入りの開発ツール「IgniteUI」の周辺について [喜帳面.net]での事例などを織り交ぜながら、メモを残しています。

対象の環境は、ASP.NET MVC4 RazorでIgniteUIは2013 Volume 2 です。ちょっと古いけどあしからず。


 さて、今回は前回に続き、igGridのロードオンデマンドについてのメモです。

Grid上の表示不要列をクライアント側で描画後に隠すのではなく、ロードオンデマンド機能を使って、列自体の定義をしないことによって見せなくする方法について記載します。

まず、ロードオンデマンド機能を使う場合のViewの記述はこんな感じになります。

<_sellistOndm>

ポイントになりそうな部分は、以下の2行です。

3行目:使用modelは「 Infragistics.Web.Mvc.GridModel」にする

15行目:@(Html.Infragistics().Grid(Model))

Viewの定義はこれだけです。

 あとは、ControllerでModelを用意しViewを呼び出します。

[喜帳面.net]の「取引伝票の発行」では抽出条件の入力後に[一覧表示]ボタンをクリックするとigGridを持つPartialViewを表示するようにしています。

 

Controllerの抜粋

14行目: GetGridModelを呼び出してInfragistics.Web.Mvc.GridModelを生成しています。this.repository.GetGridModelの部分は各プロジェクト要件に合わせてください。

15行目:前述のView名とModelを指定してPartialViewResultを返しています。 

 ここまでは単純でした。ロードオンデマンド機能の肝は「GridModel」を作成する部分にあります。上記の例では14行で呼び出される「GetGridModel」の中身の記述です。

GetGridModel」の例示ができればいいのですが、この部分はボリュームのあるコードにりますので要点だけ記述いたします。(私のコードがきれいにできてないってのが大きな理由です)

 


GetGridModelはこんな感じになります

1.GridModelを用意します。

gridModel = new GridModel();てな感じ。事前にusing Infragistics.Web.Mvc;入れておいてください。

2.親階層の定義を登録します。

 VisualStudioでGridModelの定義を確認してください。60超の項目が存在しますが、いずれもロードオンデマンド機能を使用しない場合にView(cshtml)で定義する項目たちなのでgridをいくつか作成したことのある方なら馴染みのある項目名です。また各項目の意味についてはヘルプのオプションを見ると理解できると思います。

拙作[喜帳面.net]では、現在、以下の項目に値をセットしています。

AutoGenerateColumns = False
AutoGenerateLayouts= False
ColumnLayouts  ※後述 子階層の定義を格納します
Columns        ※後述 親階層の各カラムの定義を格納します。
DataSourceUrl  ※後述 親階層のデータ取得URL
Height
ID(gridの要素ID)
LoadOnDemand = true
PrimaryKey = "PKey " ※PrimaryKeyのカラム名
Width
Features      ※後述

DataSourceUrlのセット

親階層のレコード取得時のURL。コントローラーのAction名を指定

例えば、DataSourceUrl = Url.Action("GetListParentData", new { Joken1 = joken1 });

 

※Columnsのセット

 ColumnsはList<GridColumn>型です。GridColumnの定義を確認してください。11項目ほどの項目がありますが、いずれもロードオンデマンド機能を使用しない場合にView(cshtml)の.Columns({column.For})で定義する項目たちです。

GridColumn clm = new GridColumn();
clm.DataType = "number";
clm.Format = "#,##0";
clm.HeaderText = "金額";
clm.Key = "Kingaku" ;
clm.Template = "<div align=right>${Kingaku}</div>";
clm.Width = "100px";
....割愛...
Columns.Add(clm)

こんな感じで、Grid上への表示順に必要な列分ColumnsにGridColumnを追加します。

grid上に表示しないのなら、追加しなければいい という訳です。また、隠し列にする場合はHidden = true;とします。 

 

Featuresのセット

 FeaturesはList<GridFeature>型です。GridFeatureの定義はDictionaryになっていますが、いずれもロードオンデマンド機能を使用しない場合にView(cshtml)の..Featuresで定義する項目たちです。

使用する機能のClassを用意して順次Featuresに追加します。

例えば、Pagingの場合なら 

GridPaging fp = new GridPaging();
fp.Type = OpType.Local;
fp.Inherit = false;
fp.PageSize = 10;
fp.VisiblePageCount = 1;
....割愛...
Features.Add(fp);

こんな感じです。

 Featuresで使用するclassには以下のものがあります。(全部ではありません。一部です)機能名の頭にGridをつけたらclass名になるような命名ですね。

GridPaging

GridSelection

GridRowSelectors

GridColumnMoving

GridFiltering(※)

GridSorting(※)

GridResizing

GridTooltips(※)

GridUpdating(※)

GridHiding(※)

, etc

尚、(※)がついているclassについては、ColumnSettingsのListをもっていますので、Columnsのセット時同様、カラム毎の情報をセットする必要があります(ある場合があります)。

以上、親階層のセット項目でした。

階層型のGridでない場合は以上で終わりです。

 

3.子階層の定義を登録します。

 ※ColumnLayouts のセット 

次に階層型Gridの場合の子階層の情報をColumnLayoutsにセットします。

 ColumnLayoutsはList<IGridModel>型になっています。

いずれもロードオンデマンド機能を使用しない場合にView(cshtml)の..ColumnLayouts(layouts =>{}で定義する項目たちです。

親階層で各項目にセットしたのと同様に子階層の情報についてGridColumnLayoutModelを作成し値セットしたうえでColumnLayoutsにaddといった手順でいけます。

例えば、こんな感じです。

 

 もし、子階層の下に孫階層がある場合はm子階層のColumnLayoutsに孫階層の情報をセットすることになります。


再び<Controller> について。

今までの手順で、igGrideの定義が準備できました。

次に、データの受け渡し部分です。

前述の<Controller>の_sellistOndmアクションが実行されたところで、クライアントに igGrideの定義が渡されます。その定義内の「DataSourceUrl」で指定したアクションが呼び出されます。このアクションで親階層用のデータを渡します。

前述の例では「DataSourceUrl」にアクション名"GetListParentData"と引数"Joken1"をセットしていました。対応するアクションの記述はこんな感じです。

//Grid親階層のデータを返します
public JsonResult GetListParentData(int Joken1)
{
    //伝票一覧の取得
    List<Parentdata> itemList = new List<Parentdata>(); //親階層用一覧のListを用意
    this.repository.GetGridData(Joken1, itemList);      //Listにデータを格納
    return Json(itemList, JsonRequestBehavior.AllowGet);//ListをJsonにして返す
}

 次に、子階層データの受け渡し部分。

子階層のDataSourceUrlに ”GetListChildData” をセットしたとして。以下のようなかんじになります。

//Grid子階層のデータを返します
public JsonResult GetListChildData(string path, string layout)
{
    List<Childdata> itemList = new List<Childdata>();         //子階層用一覧のListを用意
    this.repository.GetGridChildData(path, layout, itemList); //Listにデータを格納
    return Json(itemList, JsonRequestBehavior.AllowGet);      //ListをJsonにして返す
}

 引数"path"には"名前:値"の形式でセットされます。
名前は親階層の[PrimaryKey]にセットした列名。
値には展開した親行の[PrimaryKey]の値。となります。

 引数"layout"には子階層の[key]にセットした値がセットされてきます。

これら引数の情報より、子階層のデータを取得して返してあげます。


以上で、ロードオンデマンドを使用したigGridの出来上がりです。

 GridModel を作成する部分にちょっと手間がかかりますが、汎用的に使い回しできるclassに仕上げておきたいですね。

そこまでできたら、cshtmlのgridoptionを直接記述するよりも、手軽で汎用性も高く保守面でも有利になるように私は思うのですが、いかかでしょうか?

今回は以上です。