QA@IT

ASP.NET[C#]でのw2ui gridの使用方法について

9038 PV

いつもお世話になっております。
現在ASP.NET[C#]でWebアプリケーション(Webフォーム)を作成しています。
GridViewに1000行30列ほどのデータを表示する画面があるのですが、下記の条件でかつ素早く表示させたいと思っています。

  • ヘッダー固定可能
  • ボタン列あり
  • フィルターや検索が可能
  • ページングはなし

調べた結果、w2uiのgridがとても便利そうだと感じ実装を試みたのですが
サーバーで構築したデータをどのようにしてクライアント側のJavaScriptに渡すのかが分からず
実装出来ていません。
ASP.NETでどのように使用するのでしょうか?
また、w2uiだけでなくみなさんは大量のデータを一度に表示するためにどのような方法を用いているのでしょうか?
ご教授お願いいたします。

[環境]
Windows7,VWD2010Express,C#,IE9

  • まる投げしないでもっと自分でどうすれば良いかを調べてみませんか? その上で、例えば(あくまで例えば)「JSON 文字列を作って○○○すれば渡せるが、実際にそれを ASP.NET Web アプリで SQL Server から取得して JSON 文字列にして渡す仕組みを作るにはどうすればいいか」というような質問にできませんか? -
  • 仰る通りです。http://qiita.com/rbtnn/items/b2ec6c7dee792e66ac75
    のサイトからサーバー⇒クライアントにJSON文字列を渡す方法は分かったのですがこれをどのようにw2uiで表示させるのかが分からず困っていました。
    -
  • また、この方法はWebページを2つ使っているがこれが標準的な方法なのかということ。それ以前に自分がやろうとしていることが本当に合っているのかが不安になり丸投げするような質問になってしまいました。申し訳ありません。 -
  • 「クライアントにJSON文字列を渡す方法は分かった」のであれば http://w2ui.com/web/docs/grid の Example 2 に書いてある形式で渡せば、そのあとは表示まで全部 Grid が面倒見てくれるはずです。一体全体何が分からないのですか? -
  • 「この方法はWebページを2つ使っているがこれが標準的な方法なのか」とか書いてあるところを見ると、「クライアントにJSON文字列を渡す方法は分かった」というのが疑わしいのですが、何がどこまで分かったのでしょうか? -
  • 表示用とAJAX通信用でページを分けた方が良いというのは載っていたのですが、仕組みは理解していませんでした。勉強します。 -

回答

SurferOnWwwさん、ありがとうございます。
自分でも一応DataTableの内容を表示させることが出来たので載せます。
WebForm1.aspx

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link rel="stylesheet" type="text/css" href="Styles/w2ui-1.3.min.css" />
    <script src="Scripts/jquery-1.11.3.min.js"></script>
    <script src="Scripts/w2ui-1.3.min.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div id="grid" style="height: 600px;">
    </div>
    </form>
</body>
<script type="text/javascript">
    $(function () {
        $('#grid').w2grid({
            name: 'grid',
            url: 'WebForm2.aspx',
            columns: [
                { field: 'fname', caption: 'First Name', size: '30%' },
                { field: 'lname', caption: 'Last Name', size: '30%' },
                { field: 'email', caption: 'Email', size: '40%' },
                { field: 'sdate', caption: 'Start Date', size: '120px' },
            ]
        });
    });
</script>
</html>

WebForm2.aspx.cs

public partial class WebForm2 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var c = this.ConvertDataTabletoString();
            Response.ContentType = "text/javascript";
            Response.Output.Write(c);
            Response.End();
        }
        public string ConvertDataTabletoString()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("fname"); dt.Columns.Add("lname"); dt.Columns.Add("email");
            dt.Columns.Add("sdate");
            for (int i = 0; i < 1000; i++)
            {
                DataRow row = dt.NewRow();
                row["fname"] = "a";
                row["lname"] = "b";
                row["email"] = "c";
                row["sdate"] = "2015/12/16";
                dt.Rows.Add(row);
            }
            System.Web.Script.Serialization.JavaScriptSerializer serializer = new
            System.Web.Script.Serialization.JavaScriptSerializer();
            List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
            foreach (DataRow dr in dt.Rows)
            {
                var dict = new Dictionary<string, object>();
                foreach (DataColumn col in dt.Columns)
                {
                    dict[col.ColumnName] = dr[col];
                }
                rows.Add(dict);
            }
            string ret = serializer.Serialize(rows);

            ret = "{\"status\" : \"success\",\"total\":1000,\"records\":" + ret + "}";

            return ret;
        }
    }

SurferOnWwwさんの載せてくださったコードも自分で実行して勉強します。
w2uiについてはもう少し自分がやりたいことが出来るか調べてみようと思います。

編集 履歴 (0)

コメントに「Example 2 に書いてある形式で渡せば、そのあとは表示まで全部 Grid が面倒見てくれるはず」と書いておきながら、もしできなかったら何ですので、バージョン 1.4.3 の .js と .css をダウンロードして検証してみました。

Example 2 に書いてあることは間違いないようで(間違っているところもありますが、今回の検証には関係ないのでその話は割愛)、期待した結果が得られます。

せっかく作ったので検証に使ったコードをご参考にアップしておきます。

Microsoft が提供している SQL Server サンプルデータベース Northwind の Orders テーブル(14 フィールド x 830 レコード)を使用しています。

データを取得し、JSON 文字列にして渡すのは HTTP ハンドラを使用しました。コードは以下の通りです(Web サイトプロジェクトのものです)。

<%@ WebHandler Language="C#" Class="_0139_w2uiOrdersHandler" %>

using System;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Runtime.Serialization;
using System.Web.Configuration;
using System.Collections.Generic;
using System.Runtime.Serialization.Json;

public class _0139_w2uiOrdersHandler : IHttpHandler 
{    
  public void ProcessRequest (HttpContext context) 
  {
    GridData data = new GridData();
    data.records = new List<Record>();

    string connString = 
        WebConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
    string query = "SELECT * FROM [Orders]";
    using(SqlConnection conn = new SqlConnection(connString))
    {
      conn.Open();
      using (SqlCommand cmd = new SqlCommand(query, conn))
      {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
          if (reader != null)
          {
            while (reader.Read())
            {
              Record record = new Record();
              record.OrderID = reader.GetInt32(0);
              record.CustomerID = reader.IsDBNull(1) ? null : reader.GetString(1);
              record.EmployeeID = reader.IsDBNull(2) ? null : (int?)reader.GetInt32(2);
              record.OrderDate = reader.IsDBNull(3) ? null : (DateTime?)reader.GetDateTime(3);
              record.RequiredDate = reader.IsDBNull(4) ? null : (DateTime?)reader.GetDateTime(4);
              record.ShippedDate = reader.IsDBNull(5) ? null : (DateTime?)reader.GetDateTime(5);
              record.ShipVia = reader.IsDBNull(6) ? null : (int?)reader.GetInt32(6);
              record.Freight = reader.IsDBNull(7) ? null : (decimal?)reader.GetDecimal(7);
              record.ShipName = reader.IsDBNull(8) ? null : reader.GetString(8);
              record.ShipAddress = reader.IsDBNull(9) ? null : reader.GetString(9);
              record.ShipCity = reader.IsDBNull(10) ? null : reader.GetString(10);
              record.ShipRegion = reader.IsDBNull(11) ? null : reader.GetString(11);
              record.ShipPostalCode = reader.IsDBNull(12) ? null : reader.GetString(12);
              record.ShipCountry = reader.IsDBNull(13) ? null : reader.GetString(13);
              data.records.Add(record);
             }
           }
         }
       }
    }

    // キャッシュは無効にする
    context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    context.Response.Cache.SetExpires(DateTime.Now.ToUniversalTime());
    context.Response.Cache.SetMaxAge(new TimeSpan(0, 0, 0, 0));

    context.Response.ContentType = "application/json; charset=utf-8";

    data.status = "success";
    data.total = data.records.Count;

    // 参考記事「方法 : JSON データをシリアル化および逆シリアル化する」
    // https://msdn.microsoft.com/ja-jp/library/bb412179(v=vs.110).aspx        
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(GridData));
    ser.WriteObject(context.Response.OutputStream, data);

    // DateTime 型は \/Date(836406000000+0900)\/ のようにシリアライズされる。
  }

  public bool IsReusable 
  {
    get 
    {
      return false;
    }
  }

}

[DataContract]
internal class GridData
{
    [DataMember]
    internal string status { get; set; }

    [DataMember]
    internal int total { get; set; }

    [DataMember]
    internal List<Record> records { get; set; } 

}

[DataContract]
internal class Record
{
    [DataMember]
    internal int OrderID { get; set; }

    [DataMember]
    internal string CustomerID { get; set; }

    [DataMember]
    internal int? EmployeeID { get; set; }

    [DataMember]
    internal DateTime? OrderDate { get; set; }

    [DataMember]
    internal DateTime? RequiredDate { get; set; }

    [DataMember]
    internal DateTime? ShippedDate { get; set; }

    [DataMember]
    internal int? ShipVia { get; set; }

    [DataMember]
    internal decimal? Freight { get; set; }

    [DataMember]
    internal string ShipName { get; set; }

    [DataMember]
    internal string ShipAddress { get; set; }

    [DataMember]
    internal string ShipCity { get; set; }

    [DataMember]
    internal string ShipRegion { get; set; }

    [DataMember]
    internal string ShipPostalCode { get; set; }

    [DataMember]
    internal string ShipCountry { get; set; }    
}

それを以下のように url に設定すれば(以下のコードで 0139-w2uiOrdersHandler.ashx が上記の HTTP ハンドラ)、自動的に HTTP ハンドラに非同期呼び出しがかかって JSON 文字列が取得され、Grid にデータが表示されます。

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
    <script src="/Scripts/jquery-1.8.3.js" type="text/javascript"></script>
    <script src="/Scripts/w2ui-1.4.3.js" type="text/javascript"></script>
    <link href="/Styles/w2ui-1.4.3.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript">
    //<![CDATA[
        $(function () {
            $('#myGrid').w2grid({
                name: 'myGrid',
                url: '0139-w2uiOrdersHandler.ashx',
                columns: [
                    { field: 'OrderID', caption: 'Order ID', size: '7%' },
                    { field: 'CustomerID', caption: 'Customer ID', size: '7%' },
                    { field: 'EmployeeID', caption: 'Employee ID', size: '7%' },
                    { field: 'OrderDate', caption: 'Order Date', size: '7%' },
                    { field: 'RequiredDate', caption: 'Required Date', size: '7%' },
                    { field: 'ShippedDate', caption: 'Shipped Date', size: '7%' },
                    { field: 'ShipVia', caption: 'Ship Via', size: '7%' },
                    { field: 'Freight', caption: 'Freight', size: '7%' },
                    { field: 'ShipName', caption: 'Ship Name', size: '7%' },
                    { field: 'ShipAddress', caption: 'Address', size: '7%' },
                    { field: 'ShipCity', caption: 'City', size: '7%' },
                    { field: 'ShipRegion', caption: 'Region', size: '7%' },
                    { field: 'ShipPostalCode', caption: 'Postal Code', size: '7%' },
                    { field: 'ShipCountry', caption: 'Country', size: '7%' }
                ]                
            });
        });
    //]]>
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div id="myGrid" style="height: 450px"></div>
    </form>
</body>
</html>

スクロールは、Chrome 最新版なら何とか我慢できる程度に動きますが、IE9 あたりだと使い物にならないレベルの遅さでした。

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。