喜帳面の日記

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

Visual Studio Express 2012 for Web でいってみる 21.Ignite UIを使ってみた。

以前の記事、
Visual Studio Express 2012 for Web でいってみる 17.PartialViewとページング
http://sannomiyanotes.hatenablog.com/entry/20121225/1356428615
このページでPartialViewとページングにつてメモしたのですが、このとき
結構な量のコード作成が必要だしCSSとかビジュアルにも手がかかる、はなっから高機能なjQueryプラグインを使った方がいいのでは?
という気になってきました。
そこで、『高機能なjQueryプラグイン』ってやつをを探してみたところ
Ignite UIがいいかんじだったので試使用してみました。
以下はその試使用したときのメモ書きをまとめたものです。
Ignite UIでどんなことができるかとか、については以下のURLを参照ください。
http://jp.infragistics.com/Product.aspx?id=18974#Overview

さて、Ignite UIですが残念ながら有償です。初年度¥57,750(税込)で2年目以降は半額となるようです。おじさんのお小遣いからの出費としては高額ですが、いろんな機能がついて、UIも統一でき、きっとバグも出にくいだろう。Webのデザイン回りやJavaScriptなんかにはからきしな私には向いてる気がします。

※2015/07/16 追記:上記の価格についての情報は、このメモを最初に掲載した時点(2013年4月)での情報です。現在の価格は異なります。最新の価格については販売元にお問い合わせください。

 

今回は、Ignite UIのコンボとグリッドを使って、「17.PartialViewとページング」で作った商品一覧の表示にチャレンジします。

 

1.ASP.NET MVC4 プロジェクトの作成

Visual Studio Express 2012 for Web を立ち上げて、新しいプロジェクトを選択。

テンプレートの選択は、

[Visual C#]-[ASP.NET MVC4 Webアプリケーション]-

[インターネットアプリケーション]-ビューエンジン[Razor]と指定します。

念の為、デバッグ(F5)でホームページが表示されることを確認します。

 

2.Ignite UIのインストール

トライアル版をダウンロードしてインストールします。インストールの詳細は以下のページを参照ください。

http://jp.infragistics.com/Product.aspx?id=18974#Downloads

続いて、プロジェクトへIgnite UIをセットアップしていきます。

 

3.ファイルのコピー

Ignite UIがインストールされた状態で、スタートボタンー全てのプログラムで[Infragistics]フォルダを開きます。

f:id:SannomiyaNotes:20130203085012p:plain

製品ファイルをクリックすると、[IgniteUI 2012.2]フォルダが開きます。

Visual Studio Express 2012 for Webで、1で作成したプロジェクトを開き、

 
3-1.[Content]フォルダIgnite 用の新しいフォルダ[IG]を追加します。(フォルダ名は任意です)
そのフォルダに製品ファイルより[css]フォルダをコピー&ペーストします。
 
3-2.同様に、[Scripts]フォルダ新しいフォルダ[IG]を追加します。
そのフォルダに製品ファイルより[js]フォルダをコピー&ペーストします。
 

f:id:SannomiyaNotes:20130203092548p:plain

 
3-3.[bin]フォルダにdllファイルを追加します。
ソリューションエクスプローラーの「全てのファイルを表示」アイコンをクリックし[bin]フォルダを表示し、
そこに製品フォルダ[IgniteUI 2012.2]-[MVC]-[MVC4]-[Bin]内の
Infragistics.Web.Mvc.dll
Infragistics.Web.Mvc.Mobile.dll
コピー&ペーストします。

f:id:SannomiyaNotes:20130203093359p:plain

 

4.参照設定

ソリューションエクスプローラーの[参照設定]フォルダを右クリックし[参照の追加]をクリック、参照マネージャー画面より当該プロジェクトの[bin]をブラウズし

Infragistics.Web.Mvc.dll
Infragistics.Web.Mvc.Mobile.dll
への参照を追加します。
[参照設定]フォルダに上記参照が追加されます。
続いて、追加した参照をそれぞれ、右クリックしてプロパティを開き
[ローカルコピー]を false から true に変更します。
この変更を忘れると、デバッグでは実行できても「発行」後の実行時にエラーになります。
 

5.infragistics.loaderのbundleを追加

[App_Start]フォルダを開き[BundleConfig.cs]を編集します。
既存のbundle定義に、以下の行を追加します。
bundles.Add(new ScriptBundle("~/bundles/infragistics.loader").Include(
                        "~/Scripts/IG/js/infragistics.loader*"));

6.マスタページの変更[_Layout.cshtml]
 
@Scripts.Render("~/bundles/jquery")の位置を<head>に移しました。
 
<!DOCTYPE html>
<html lang="ja">
    <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <meta charset="utf-8" />
        <title>@ViewBag.Title ? マイ ASP.NET MVC アプリケーション</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")

@* ADD *@
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/jqueryui")
        @*↓このタイミングでinfragistics.loaderをScripts.Renderするとエラーになる場合あり*@
        @*@Scripts.Render("~/bundles/infragistics.loader")*@ 

    </head>
    <body>
        <header>
            <div class="content-wrapper">
                <div class="float-left">
                    <p class="site-title">@Html.ActionLink("ここにロゴを入れてください", "Index", "Home")</p>
                </div>
                <div class="float-right">
                    <section id="login">
                        @Html.Partial("_LoginPartial")
                    </section>
                    <nav>
                        <ul id="menu">
                            <li>@Html.ActionLink("ホーム", "Index", "Home")</li>
                            <li>@Html.ActionLink("バージョン情報", "About", "Home")</li>
                            <li>@Html.ActionLink("連絡先", "Contact", "Home")</li>

                            @*↓テスト用に追加*@
                            <li>@Html.ActionLink("商品指定と検索", "ShouhinSitei", "shouhin")</li>
                        </ul>
                    </nav>
                </div>
            </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
                @RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
                <div class="float-left">
                    <p>&copy; @DateTime.Now.Year ? マイ ASP.NET MVC アプリケーション</p>
                </div>
            </div>
        </footer>
        @*↓infragistics用の変更jqueryのLoadはheadで行うようにコメントアウト*@
        @* @Scripts.Render("~/bundles/jquery")*@

        @*↓この行はコメントアウトすると[登録]等が動かなくなる *@
        @RenderSection("scripts", required: false)
    </body>
</html>

 
ここまでで、Ignite UI をASP.NET MVC4 Webアプリケーションプロジェクトで利用するための準備完了です。
ここからは、実際に Ignite UIのコンボとグリッドを使う、「商品コード検索」を作っていきます。出来上がりはこんな感じです。

f:id:SannomiyaNotes:20130204143453p:plain

 
6.Modelを追加[Shouhin.cs]
今回はデータをデータベースからではなくて直接Listで作成してます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

//以下のNameSpaceを追加
using System.ComponentModel;

namespace Mvc4ApplicationL.Models
{
    /// <summary>
    /// 商品コードの指定ページ用ビューモデル
    /// </summary>
    public class VM_ShouhinSitei
    {
        [DisplayName("商品コード")]
        public int shouhinCD { get; set; }
    }
    /// <summary>
    /// 商品区分の一覧用
    /// </summary>
    public class ShouhinKubun
    {
       public int    KubunCD  { get; set; }
       public string Kubunmei { get; set; }
    }
    public class ShouhinKubunModels
    {
        public static IQueryable<ShouhinKubun> GetShouhinKubunList()
        {
         List<ShouhinKubun> ItemList = new List<ShouhinKubun>();
         ItemList.Add(new ShouhinKubun { KubunCD = 0, Kubunmei = "すべての商品区分" });
         ItemList.Add(new ShouhinKubun { KubunCD = 1, Kubunmei = "飲料" });
         ... 省略 ...
         return ItemList.AsQueryable<ShouhinKubun>();
         }
    }
    /// <summary>
    /// 商品の一覧用
    /// </summary>
    public class Shouhin
    {
        public int    ShouhinCD    { get; set; }
        public string ShouhinName  { get; set; }
        public int    ShouhinKubun { get; set; }
    }
    public class ShouhinModels
    {
        public static IQueryable<Shouhin> GetShouhinList(Nullable<int> ShouhinKubun)
        {
         //商品データ
         List<Shouhin> shouhinList = new List<Shouhin>();
         shouhinList.Add(new Shouhin { ShouhinCD = 1, ShouhinName = "果汁100% オレンジ", ShouhinKubun = 1 });
         shouhinList.Add(new Shouhin { ShouhinCD = 2, ShouhinName = "果汁100% グレープ", ShouhinKubun = 1 });
            ... 省略 ...
         shouhinList.Add(new Shouhin { ShouhinCD = 124, ShouhinName = "綿菓子はつゆき", ShouhinKubun = 3 });
         
         //
         if (ShouhinKubun != null)
         {
             int shouhinYubunMIN = (int)ShouhinKubun;
             int shouhinYubunMAX = (int)ShouhinKubun;
             if (ShouhinKubun == 0//全ての場合、MINとMAXをセット。
             {
                 shouhinYubunMIN = 1;
                 shouhinYubunMAX = 99;
             }
             IEnumerable<Shouhin> source =
                   from s in shouhinList
                   where s.ShouhinKubun >= shouhinYubunMIN && s.ShouhinKubun <= shouhinYubunMAX
                   orderby s.ShouhinCD
                   select s;
             return source.AsQueryable<Shouhin>();
            }
            else
            {
             List<Shouhin> shouhinListNull = new List<Shouhin>();
             return shouhinListNull.AsQueryable<Shouhin>();
            }
        }
    }    
}
***
7.Controllerを追加[ShouhinController.cs]
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using Infragistics.Web.Mvc;
using Mvc4ApplicationL.Models;
using System.Reflection;

namespace Mvc4ApplicationL.Controllers
{
    public class ShouhinController : Controller
    {
        //■■商品指定メインページ
        public ActionResult ShouhinSitei()
        {
            return View();
        }
        //■■商品検索ページ
        // 商品一覧をPartialViewで返します。
        [AjaxOnly]
        public ActionResult _pShouhinKensaku(string TergetElement)
        {
            ViewBag.KensakuTergetElement = TergetElement;
            return PartialView("_pShouhinKensaku");
        }
        // 商品区分の一覧をJSONで返します。
        public JsonResult ShouhinKubunList()
        {
            IQueryable<ShouhinKubun> data = ShouhinKubunModels.GetShouhinKubunList();
            return Json(data, JsonRequestBehavior.AllowGet);
        }
        // 商品一覧をViewで返します。
        [GridDataSourceAction]
        public ActionResult GetShouhinList(Nullable<int> cd)
        {
            return View(Models.ShouhinModels.GetShouhinList(cd));
        }
        //Jsonで商品データを渡します。
        public JsonResult GetJsonDataShouhin(Nullable<int> cd)
        {
            var model = ShouhinModels.GetShouhinList(cd);
            return Json(model, JsonRequestBehavior.AllowGet);
        }
        //Attribute[AjaxOnly]
        public class AjaxOnlyAttribute : ActionMethodSelectorAttribute
        {
            public override bool IsValidForRequest(
            ControllerContext controllerContext, MethodInfo methodInfo)
            {
                return controllerContext.HttpContext.Request.IsAjaxRequest();
            }
        }
    }
}
8.Viewの変更と追加
8-1.[Views]フォルダに新しいフォルダ[Shouhin]を追加します。
8-2.[Views] - [Shouhin]にビューページ[ShouhinSitei.cshtml]を追加します。
<商品コード指定ページ>
@model Mvc4ApplicationL.Models.VM_ShouhinSitei
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)

    <fieldset>
       <legend>VM_ShouhinSitei</legend>
        <div class="input-Line" style = "float:left;width:100%;height:40px;line-height:30px;">
            <span class="editor-label" > 
                @Html.LabelFor(model => model.shouhinCD,new{ style="width:80px;float:left;mar;margin:4px;" }) </span>
            <span class="editor-field" >
                @Html.EditorFor(model => model.shouhinCD,null,"input-shouhinCD",null)
                @Html.ValidationMessageFor(model => model.shouhinCD)
            </span>

            @*Link1:初回の商品検索呼び出しはAjax.ActionLinkで*@
            <span class="KensakuLink" id="linkShouhinKensaku">
                 @Ajax.ActionLink(" ","_pShouhinKensaku","Shouhin",
                   new {TergetElement="input-shouhinCD"},@*選択結果を返す要素名をパラメータ渡し*@
                   new AjaxOptions() {
                        HttpMethod = "POST"
                      ,UpdateTargetId = "pvShouhinKensaku"},
                   new {
                       style = @"background: url('../../Content/themes/base/images/ui-icons_2e83ff_256x240.png')no-repeat center right; background-position: -160px -110px; -moz-transform: scale(2.0); -webkit-transform: scale(2.0); -o-transform: scale(2.0); -ms-transform: scale(2.0); margin:10px;padding-left: 5px; height:15px; width:10px; float:left; cursor:pointer;"
                       })
           </span>
            @*Link2:2回目以降に商品検索ビューはhide→showで表示*@
            <span class="KensakuLink" id="ShowShouhinKensaku" 
                  style = "display: none; background: url('../../Content/themes/base/images/ui-icons_2e83ff_256x240.png')no-repeat center right; background-position: -160px -110px; -moz-transform: scale(2.0); -webkit-transform: scale(2.0); -o-transform: scale(2.0); -ms-transform: scale(2.0); margin:10px; padding-left: 5px; height:15px; width:10px; float:left; cursor:pointer;"
                     }></span>
        </div>
        <style>#input-shouhinCD {width:100px;height:20px;float:left;}</style>

    </fieldset>
}
 @*商品検索の部分ビュー挿入部分*@
 <div id="pvShouhinKensaku" style="width:415px;"></div>

<script type="text/javascript">
        //初回の商品検索ビューの呼び出し
        $("#linkShouhinKensaku").click(function () {
            $('#ShowShouhinKensaku').show();
            $('#linkShouhinKensaku').hide();
        })

        //2回目以降に商品検索ビューはhide→showで表示
        $("#ShowShouhinKensaku").click(function () {
            $('#linkShouhinKensaku').hide();
            $('#pvShouhinKensaku').show();
        })
</script>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

 
8-3.[Views] - [Shared]に partial View [_pShouhinKensaku.cshtml]を追加します。
<商品コード検索部分ページ>
@using Mvc4ApplicationL.Models;
@using Infragistics.Web.Mvc;

@Scripts.Render("~/bundles/infragistics.loader")
@(Html.Infragistics().Loader()
                .ScriptPath(Url.Content("~/Scripts/IG/js/"))
                .CssPath(Url.Content("~/Content/IG/css/"))
                .Resources("igShared,igDialog")
                .Render())

<div style="border:solid;border-color: #CFCFCF";border-width: 0.1px;>

    @*↓グリッドを閉じるボタン *@
    <div class="CloseKensaku" id="closeKensaku" 
         style  = "float:right; cursor:pointer; background: url('../../Content/themes/base/images/ui-icons_2e83ff_256x240.png')no-repeat center right; background-position: -100px -130px; -moz-transform: scale(2.0); -webkit-transform: scale(2.0); -o-transform: scale(2.0); -ms-transform: scale(2.0); height:15px; width:10px; margin:10px; padding-left: 4px;">
    </div>

    @* ↓商品区分のコンボ *@
    <div style="display: block; height: auto; width:auto;margin-left: 5px; margin-right: 5px;">
        @(Html.Infragistics().Combo()
            .ID("Combo1").Width("200px").Height("30px")
            @*商品区分の一覧をJSONで受け取る*@
            @*DataSourceUrlからはJSONで返す。gridのようにViewで返すのはダメみたい。*@
            .DataSourceUrl(Url.Action("ShouhinKubunList"))
            .ValueKey("KubunCD")
            .TextKey("Kubunmei")
            .NullText("商品区分を選択してください")
            .DataBind()
            .Render())
    </div>

    @* ↓商品のグリッド *@
    <div id="ShouhinList" style="width:650px; height: 460px;margin-left: 5px; margin-right: 5px;">
        @(Html.Infragistics().Grid<Shouhin>()
            .ID("grid1")
            .Width("400px")
            .Height("440px")
            .AutoGenerateColumns(false)
            .Columns(column =>
                {
                 column.For(x => x.ShouhinCD)
                                  .HeaderText("コード")
                                  .Width("100px")
                                  .DataType("number");
                 
                  column.For(x => x.ShouhinName)
                                  .HeaderText("商品名")
                                  .Width("200px")
                                  .DataType("string");
                 
                  column.For(x => x.ShouhinKubun)
                                  .HeaderText("区分")
                                  .Width("50px")
                                  .DataType("string");
                })
            .Features(features =>
                {
                 features.Paging().Type(OpType.Local)
                                  .VisiblePageCount(5)
                                  .ShowPageSizeDropDown(true)
                                  .PageSize(10)
                                  .PrevPageLabelText("前頁")
                                  .NextPageLabelText("次頁");
                 features.Filtering().Type(OpType.Local).Mode(FilterMode.Advanced);
                 features.Sorting().Type(OpType.Local).Mode(SortingMode.Single);
                 features.Selection().MouseDragSelect(true)
                                     .MultipleSelection(false)
                                     .Mode(SelectionMode.Row);
                 features.Resizing();
                })
            //DataSourceの指定方法は色々サポートされてます
            //.DataSourceUrl(Url.Action("GetJsonDataShouhin"))//JsonResult return Json
            .DataSourceUrl(Url.Action("GetShouhinList"))  //ActionResult return View
            .LocalSchemaTransform(true)
            .DataBind()    
            .Render()
            )
    </div>

    @* ↓メッセージダイアログ *@
    <div>
        @(Html.Infragistics().Dialog()
            .ContentID("igDialog1")
            .ShowMinimizeButton(true)
            .ShowMaximizeButton(true)
            .ShowPinButton(true)
            .Width("400px")
            .Height("500px")    
            .Render()
        )
    </div>
</div>
 @*↓ここに検索結果を返す要素IDをViewBagよりセット*@
<div id="KensakuTergetElement" style="display: none;">@ViewBag.KensakuTergetElement</div>

 @*↓ダイアログ要素*@
<div style="display: block; height: auto; width:auto;">
        <!--igDialog target element-->
        <div id="kcmnMsgDialog" style="vertical-align: bottom; display: none;" >
            <div id="kcmnMsgDialogprompt">ダイアログに表示するメッセージ要素</div>
            <button id="kcmnMsgDialogprompt_yes"    style="vertical-align: bottom; display: none;"></button>
            <button id="kcmnMsgDialogprompt_no"     style="vertical-align: bottom; display: none;"></button>
            <button id="kcmnMsgDialogprompt_cancel" style="vertical-align: bottom; display: none;"></button>
        </div>
</div>

<script type="text/javascript">
    //選択結果を格納する変数を用意
    var shouhincd = "";
    //検索結果を返す要素:ViewBag → #KensakuTergetElement → targetelementと渡される。 
    var targetelement = "#" + $(KensakuTergetElement).text();

    //×closeのクリック時は部分ビュー部分を隠す。
    $("#closeKensaku").live("click", function (e) {
        $('#pvShouhinKensaku').hide();
    });

    //コンボの選択値が変更されたとき
    $('#Combo1').live('igcomboselectionchanged', function (event, args) {
        if (args.items != null) {
            //グリッドのデータを再セットする。商品区分をパラメータで渡す。
            $('#grid1').igGrid({
                dataSource: "/Shouhin/GetShouhinList?cd=" + args.items[0].value
            });
        }
    });
    //グリッドの一覧から1行選択されたとき
    $('#grid1').live('iggridselectionactiverowchanged', function (event, args) {
        //選択された行から商品コードと商品名を取得し
        shouhincd = args.row.element[0].cells[0].textContent
        var msg = "商品=" + args.row.element[0].cells[0].textContent + ":"
                          + args.row.element[0].cells[1].textContent
        //ダイアログのメッセージ領域にセット。
        msg = "指定内容を確認してください" + "<br/>" + "<hr>" + msg + "<br/>" + "<hr>"
        $("#kcmnMsgDialogprompt").html(msg)

        //ボタンの設定[OK]と[キャンセル]を表示します
       $("#kcmnMsgDialogprompt_yes").css({ display: "" });
       $("#kcmnMsgDialogprompt_yes").igButton({ labelText: "OK" });
       $("#kcmnMsgDialogprompt_cancel").css({ display: "" });
       $("#kcmnMsgDialogprompt_cancel").igButton({ labelText: "キャンセル" });

       //ダイアログを表示します。
       $.ig.loader(function () {
            // Initialize the igDialog
            $("#kcmnMsgDialog").igDialog({
                  state: "opened"
                , trackFocus: false
                , enableHeaderFocus: false
                , closeOnEscape: false
                , showMinimizeButton: false
                , showMaximizeButton: false
                , showPinButton: false
                , imageClass: "ui-icon ui-icon-info"
                , openAnimation: "fade"
                , closeAnimation: "fade"
                , headerText: "確認してください"
                , showFooter: false
            });
        });
    });
    //ダイアログ.yesをクリック時
    $("#kcmnMsgDialogprompt_yes").live("click",function (e) {
        //ダイアログを閉じる
        $("#kcmnMsgDialog").igDialog("close");
        // 検索ビューを隠す
        $('#pvShouhinKensaku').hide();
        //選択した商品コードをターゲットにセット
        $(targetelement).val(shouhincd);
    });
    //ダイアログ.NOをクリック時
    $("#kcmnMsgDialogprompt_no").live("click", function (e) {
        $("#kcmnMsgDialog").igDialog("close");
    });
    //ダイアログ.cancelをクリック時
    $("#kcmnMsgDialogprompt_cancel").live("click", function (e) {
        $("#kcmnMsgDialog").igDialog("close");
    });
</script>

 
9.動かしてみる
マスタページの「商品指定と検索」をクリックすると以下のページが表示されます。

f:id:SannomiyaNotes:20130204153350p:plain

商品コード欄右の虫眼鏡イメージをクリックすると、商品検索部分ビューが表示されます。

f:id:SannomiyaNotes:20130204153524p:plain

商品区分のコンボで商品区分を指定します。

f:id:SannomiyaNotes:20130204153650p:plain

指定の商品区分の商品の一覧がグリッドに表示されます。

f:id:SannomiyaNotes:20130204153831p:plain

ページングが可能なことはもちろん、グリッドの見出し部分をクリックしてソートやフィルタがかけられます。

また列幅の変更も可能です。

以下はフィルタ指定ダイアログの例です。

 

f:id:SannomiyaNotes:20130204154204p:plain

 

 

f:id:SannomiyaNotes:20130204154500p:plain

また、1ページあたりの表示レコードが変更できたり、多数の機能がありここでは紹介しきれません。

さて、グリッドで行クリックすると、以下の確認ダイアログが表示されます。

f:id:SannomiyaNotes:20130204154831p:plain

このダイアログもIgnite UIを利用して表示したものです。

OKをクリックすると

f:id:SannomiyaNotes:20130204155110p:plain

もとのページの商品コードフィールドに選択した商品のコードがセットされます。

尚、商品検索の部分ビューはhideしており、虫眼鏡をクリックすると、showされて再び表示されるようにしています。

 

以上、gnite UIの簡単な?紹介でした。今回は、商品検索部分を部分ビューを使って呼び出す形式を使いましたが、ダイアログで表示する方法のサンプルもありました。

会計や販売管理など企業で利用するWebシステム開発の場合、ビジュアルはそこそこでよくて、統一性が必要になるかと思いますし、ビジュアルよりもビジネスロジックの開発によりより力を割きたい私の場合など、こんなツールは非常に有益です。おじさんのお小遣いで購入するにはちょっと高額だなという気はしますが。

今回は以上です。