WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

Razor 構文の Web ヘルパー/ページ

by WebSurfer 2012年3月20日 16:12

ASP.NET Web サイトプロジェクト(MVC でない)でも Razor 構文の Web ページ、Web ヘルパーが使用できるということを知ったので、備忘録として書いておきます。

Web サイトプロジェクトで[ヘルパー(Razor)] を追加

Web サイトプロジェクト(MVC でない)で、ソリューションエクスプローラーから[新しい項目の追加(W)]を選ぶと、上の画像のダイアログが表示され、Razor 構文の Web ページや Web ヘルパーが選択できるのが分かります。(ちなみに、Web アプリケーションプロジェクトでは Razor 関係のメニューは表示されません)

ここで、[ヘルパー(Razor)] をクリックすると、デフォルトで Helper.cshtml という名前のヘルパーが Add_Code フォルダに追加されます。その時同時に、web.config の appSettings 要素に以下の key が追加されます。(何故か、[Web ページ (Razor)]その他ではこの key は追加されません)

<appSettings>
  <add key="webpages:Enabled" value="true" />
</appSettings>

MSDN の ASP.NET のフォーラム LoginStatus コントロールで loginUrl が反映されない の原因を調べる過程で分かったことですが、< key="webpages:Enabled" value="true" /> が設定してあると、forms 要素の loginUrl に設定したリダイレクト先(ログインページ)が無視されて、/Account/Login になってしまうという問題があります。

これを回避するためには、以下のように loginUrl キーを appSettings に追加してやります。

<appSettings>
  <add key="webpages:Enabled" value="true" />
  <add key="loginUrl" value="~/login.aspx" />
</appSettings>

< key="webpages:Enabled" value="true" /> を削除すると、追加した Web ヘルパーのソースの @helper HelperName( ... ) の下に青の波線が出て、"拡張 '.cshtml' に対して登録されたビルド プロバイダーはありません。" というエラーメッセージが表示されます。

でも、自分が試した限りでは、最終的には < key="webpages:Enabled" value="true" /> を削除しても、Razor 構文の Web ページ、Web ヘルパーはビルドでき、問題なく動きました。また、ビルド後は青の波線とエラーメッセージは出なくなりました。

Razor 構文の Web ページ、Web ヘルパーの実行結果

左の画像が、自分が試した結果です。その時に使ったコードを以下にアップしておきます。

ただし、< key="webpages:Enabled" value="true" /> を削除しても、相変わらずログインのリダイレクト先が /Account/Login になってしまいます。

このあたり、訳が分かりませんが、Razor 構文の Web ページを追加すると、< key="webpages:Enabled" value="true" /> がデフォルトで設定されるのではないかと推測しています。(Web ヘルパーだけではデフォルトでは webpages:Enabled の value は ture にならない?)

webpages:Enabled は、MVC 3 Project Upgrade Tool の記事によると、Razor の MVC3 で、"to prevent .cshtml or .vbhtml files in the Views folder from being directly accessible from a web browser" のため、View フォルダの web.config に value="false" として設定するものだそうです。それ以上の説明は見つけられませんでした。

Razor Web ヘルパー (App_Code/QR.cshtml)

@helper GetHtml(string url, int pixelSize=150){
  // Google のチャートAPIを使って QR コード ( 二次元バーコード ) 
  // を生成する
  string sizeUrl = string.Format("{0}x{0}", pixelSize);
  string requestUrl = 
    string.Format(
      "http://chart.apis.google.com/chart?chs={0}&cht=qr&chl={1}",
      sizeUrl, 
      HttpUtility.UrlEncode(url));
    
  <img src="@requestUrl" alt="QR コード" />
}

Razor Web ページ (WebPage.cshtml)

<!DOCTYPE html>
<html>
  <head>
    <title></title>
  </head>
  <body>
    <p>@QR.GetHtml("http://surferonwww.info/")</p>
  </body>
</html>

Tags: ,

ASP.NET

ACT ComboBox の日本語対応

by WebSurfer 2012年3月18日 16:50

AJAX Control Toolkit (ACT) の ComboBox は日本語に対応していませんが、それを無理やり(?)、ブラウザが IE のみの場合に限り、日本語対応させてみました。

日本語対応させた AJAX Control Toolkit の ComboBox

ヒントは MDSN の Visual Studio 共通フォーラムのスレッド「AJAX ComboBoxコントロール 日本語」にありました。

ComboBox は、テキストボックス(html コードで言うと <input type="text" ... />)の onkeypress イベントで、入力された文字列をリスト(html で言うと ul, li 要素を使った一覧)の中の文字列と比較していますが、IME が ON の時は onkeypress イベントが発生しないのがうまくいかない原因のようです。

その Workaround は、IE のみの場合ですが、以下の通りです。

  1. IME モードが ON のときは onkeypress イベントが発生しないので、代わりに onkeyup イベントを利用する。そのため _onTextBoxKeyUp イベントハンドラを作成し、テキストボックスの onkeyup イベントにアタッチする。
  2. _onTextBoxKeyDown イベントハンドラで、Keycode を取得しておく(IME モード ON の時は 229 になる)。
  3. _onTextBoxKeyUp イベントハンドラで、上記 ② で取得した Keycode が 229 で、かつ KeyCode が 13(ENTER) のとき(文字変 換を確定)に、_onTextBoxKeyPress イベントハンドラを実行する。

AJAX Control Toolkit のソースコードは CodePlex のサイトから入手できます。今回の場合は、JavaScript のコード ComboBox.pre.js を入手して、関係する部分を書き換えて差し替えてやります。

具体的には以下の通りです。実際に動かして試せるよう 実験室 にアップしましたので、興味のある方は試してみてください。

<%@ Page Language="C#" %>
<%@ Import Namespace="AjaxControlToolkit" %>
<%@ Import Namespace="System.Data" %>
<%@ Register
    Assembly="AjaxControlToolkit"
    Namespace="AjaxControlToolkit"
    TagPrefix="ajaxToolkit" %>

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

<script runat="server">

  private static string[] japaneseWordListText;
  public string[] GetJapaneseWordListText()
  {
    if (null == japaneseWordListText)
    {
      string[] tempWordListText = new string[] {
        "あいうえお",
        "かきくけこ",
        "さしすせそ",
        "たちつてと",
        "なにぬねの",
        "はひふへほ",
        "まみむめも",
        "abcdef",
        "日本語",
        "東京��",
        "神奈川県"
      };            
      japaneseWordListText = tempWordListText;
    }
    return japaneseWordListText;
  }

  private static string[] wordListText;
  public string[] GetWordListText()
  {
    if (null == wordListText)
    {
      string[] tempWordListText = new string[] {
        "Alfa",
        "Alpha",
        "Bravo",
        "Charlie",
        "Delta",
        "Echo",
        "Foxtrot",
        "Golf",
        "Hotel",
        "India",
        "Juliett",
        "Juliet",
        "Kilo",
        "Lima",
        "Mike",
        "November",
        "Oscar",
        "Papa",
        "Quebec",
        "Romeo",
        "Sierra",
        "Tango",
        "Uniform",
        "Victor",
        "Whiskey",
        "X-ray",
        "Xray",
        "Yankee",
        "Zulu",
        "Zero",
        "Nadazero",
        "One",
        "Unaone",
        "Two",
        "Bissotwo",
        "Three",
        "Terrathree",
        "Four",
        "Kartefour",
        "Five",
        "Pantafive",
        "Six",
        "Soxisix",
        "Seven",
        "Setteseven",
        "Eight",
        "Oktoeight",
        "Nine",
        "Novenine"
      };
      Array.Sort(tempWordListText);
      wordListText = tempWordListText;
    }
    return wordListText;
  }
    
  protected void Page_Load(object sender, EventArgs e)
  {
    if (!Page.IsPostBack)
    {
      ComboBox1.DataSource = GetWordListText();
      ComboBox1.DataBind();

      ComboBox3.DataSource = GetJapaneseWordListText();
      ComboBox3.DataBind();
    }
  }

  protected void Button1_Click(object sender, EventArgs e)
  {
    Label1.Text = ComboBox1.SelectedItem.Text;
  }

  protected void Button3_Click(object sender, EventArgs e)
  {
    Label3.Text = ComboBox3.SelectedItem.Text;
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title>AJAX Control Toolkit ComboBox の日本語対応</title>
</head>
<body>
  <form id="form1" runat="server">
  <ajaxToolkit:ToolkitScriptManager 
    ID="ToolkitScriptManager1" 
    runat="server">
  </ajaxToolkit:ToolkitScriptManager>

  <div>
    <ajaxToolkit:ComboBox ID="ComboBox1" 
      runat="server"
      AutoCompleteMode="SuggestAppend">
    </ajaxToolkit:ComboBox>
    <asp:Button ID="Button1" 
      runat="server" 
      Text="Button" 
      OnClick="Button1_Click" />
    <asp:Label ID="Label1" runat="server">
    </asp:Label>        
  </div>

  <div>
    <ajaxToolkit:ComboBox ID="ComboBox3" 
      runat="server"
      AutoCompleteMode="SuggestAppend">
    </ajaxToolkit:ComboBox>
    <asp:Button ID="Button3" 
      runat="server" 
      Text="Button" 
      OnClick="Button3_Click" />
    <asp:Label ID="Label3" runat="server">
    </asp:Label>        
  </div>
  </form>

  <script type="text/javascript">
  //<![CDATA[

  Sys.Extended.UI.ComboBox.prototype.createDelegates = function () {
    // ①
    // IME モードが ON のときは onkeypress イベントが発生
    // しない為、代わりに onkeyup イベントを利用。
    this._textBoxKeyUpHandler = 
      Function.createDelegate(this, this._onTextBoxKeyUp);

    // ここから下はオリジナルのコードそのまま。
    this._listMouseOverHandler = 
      Function.createDelegate(this, this._onListMouseOver);
    this._listMouseOutHandler = 
      Function.createDelegate(this, this._onListMouseOut);
    this._listMouseDownHandler = 
      Function.createDelegate(this, this._onListMouseDown);
    this._listClickHandler = 
      Function.createDelegate(this, this._onListClick);
    this._listDragHandler = 
      Function.createDelegate(this, this._onListDrag);
    this._listSelectStartHandler = 
      Function.createDelegate(this, this._onListSelectStart);
    this._listMouseWheelHandler = 
      Function.createDelegate(this, this._onListMouseWheel);
    this._textBoxClickHandler = 
      Function.createDelegate(this, this._onTextBoxClick);
    this._textBoxFocusHandler = 
      Function.createDelegate(this, this._onTextBoxFocus);
    this._textBoxBlurHandler = 
      Function.createDelegate(this, this._onTextBoxBlur);
    this._textBoxKeyPressHandler = 
      Function.createDelegate(this, this._onTextBoxKeyPress);
    this._textBoxKeyDownHandler = 
      Function.createDelegate(this, this._onTextBoxKeyDown);
    this._buttonClickHandler = 
      Function.createDelegate(this, this._onButtonClick);
    this._buttonBlurHandler = 
      Function.createDelegate(this, this._onButtonBlur);
    this._buttonKeyDownHandler = 
      Function.createDelegate(this, this._onButtonKeyDown);

    this._buttonKeyPressHandler = 
      Function.createDelegate(this, this._onButtonKeyPress);
    this._documentClickHandler = 
      Function.createDelegate(this, this._onDocumentClick);
    this._documentMouseWheelHandler = 
      Function.createDelegate(this, this._onDocumentMouseWheel);
    this._popupShowingHandler = 
      Function.createDelegate(this, this._popupShowing);
    this._popupShownHandler = 
      Function.createDelegate(this, this._popupShown);
    this._popupHidingHandler = 
      Function.createDelegate(this, this._popupHiding);
  };

  Sys.Extended.UI.ComboBox.prototype.clearDelegates = function () {
    // ①
    // IME モードが ON のときは onkeypress イベントが発生
    // しない為、代わりに onkeyup イベントを利用。
    this._textBoxKeyUpHandler = null;

    // ここから下はオリジナルのコードそのまま。
    this._listMouseOverHandler = null;
    this._listMouseOutHandler = null;
    this._listMouseDownHandler = null;
    this._listClickHandler = null;
    this._listDragHandler = null;
    this._listSelectStartHandler = null;
    this._listMouseWheelHandler = null;
    this._textBoxClickHandler = null;
    this._textBoxFocusHandler = null;
    this._textBoxBlurHandler = null;
    this._textBoxKeyPressHandler = null;
    this._textBoxKeyDownHandler = null;
    this._buttonClickHandler = null;
    this._buttonBlurHandler = null;
    this._buttonKeyDownHandler = null;
    this._buttonKeyPressHandler = null;
    this._documentClickHandler = null;
    this._documentMouseWheelHandler = null;
    this._popupShowingHandler = null;
    this._popupShownHandler = null;
    this._popupHidingHandler = null;
  };

  Sys.Extended.UI.ComboBox.prototype.addHandlers = function () {

    var optionListControl = this.get_optionListControl();

    $addHandlers(
      optionListControl,
      {
        'mouseover': this._listMouseOverHandler,
        'mouseout': this._listMouseOutHandler,
        'mousedown': this._listMouseDownHandler,
        'click': this._listClickHandler,
        'drag': this._listDragHandler,
        'selectstart': this._listSelectStartHandler
      },
      this);

    $addHandlers(
      this.get_textBoxControl(),
      {
        // ①
        // IME モードが ON のときは onkeypress イベントが発生
        // しない為、代わりに onkeyup イベントを利用。
        // これ以外はオリジナルのコードそのまま。
        "keyup": this._textBoxKeyUpHandler,

        "click": this._textBoxClickHandler,
        "focus": this._textBoxFocusHandler,
        "blur": this._textBoxBlurHandler,
        "keypress": this._textBoxKeyPressHandler
      }, 
      this);

    if (Sys.Browser.agent == Sys.Browser.InternetExplorer ||
      Sys.Browser.agent === Sys.Browser.Safari ||
      Sys.Browser.agent === Sys.Browser.WebKit) {
      $addHandler(
        this.get_textBoxControl(),
        "keydown", 
        this._textBoxKeyDownHandler);
    }

    $addHandlers(
      this.get_buttonControl(),
      {
        'click': this._buttonClickHandler,
        'blur': this._buttonBlurHandler,
        'keydown': this._buttonKeyDownHandler,
        'keypress': this._buttonKeyPressHandler
      }, 
      this);

    $addHandler(
      document,
      'click', 
      this._documentClickHandler);

    if (typeof (optionListControl.onmousewheel) === 'undefined') {
      $addHandler(
        optionListControl,
        'DOMMouseScroll', 
        this._listMouseWheelHandler);
      $addHandler(
        document,
        'DOMMouseScroll', 
        this._documentMouseWheelHandler);
    }
    else {
      $addHandler(
        optionListControl,
        'mousewheel', 
        this._listMouseWheelHandler);
      $addHandler(
        document,
        'mousewheel', 
        this._documentMouseWheelHandler);
    }
  };

  var keycodeOnTextBoxKeyDown = "";

  Sys.Extended.UI.ComboBox.prototype._onTextBoxKeyDown = function (e) {

    // ②
    // _onTextBoxKeyDown 時に Keycode を取得
    // (IME モード ON の時は 229)
    keycodeOnTextBoxKeyDown = this._getKeyboardCode(e);

    // ここから下はオリジナルのコードそのまま。
    var enterResult = this._handleEnterKey(e);
    if (enterResult != null) {
      return enterResult;
    }

    this._handleArrowKey(e);

    var erasureKeyResult = this._handleErasureKeys(e);
    if (erasureKeyResult != null) {
      return erasureKeyResult;
    }

    return true;

  };

  // ①
  // IME モードが ON のときは onkeypress イベントが発生
  // しない為、代わりに onkeyup イベントを利用。
  Sys.Extended.UI.ComboBox.prototype._onTextBoxKeyUp = function (e) {

    // ③
    // onkeyup時に②で取得した Keycode が 229 で
    // かつ KeyCode が 13(ENTER)のときに(文字変
    // 換を確定)、_onTextBoxKeyPress を Call する。
    if (keycodeOnTextBoxKeyDown == 229 && e.keyCode == 13) {
      this._onTextBoxKeyPress(e);
    }
  };

  //]]>  
  </script>
</body>
</html>

Tags: , ,

AJAX

ListView に配置した CheckBox で選択

by WebSurfer 2012年3月17日 17:03

ユーザーが ListView 上の CheckBox にチェックを入れて複数の項目を選択後、ポストバックしてサーバー側で選択された項目を取得するという例です。

ListView に配置した CheckBox の選択結果をサーバーで取得

特に難しいことではないのですが、GridView と違って、ListView の場合はあまり例が見つからないので、忘れないように書いておきます。

ListView は「項目」(ListViewItem オブジェクト)で構成されており、そのコレクションは Items プロパティで取得できます。

後はループを回して、ListViewItem オブジェクトの中から FindControl メソッドで CheckBox オブジェクトを探し、チェックがついているかどうかを調べることができます。

そのサンプルコードは以下の通りです。

<%@ 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">

  // ListView に CheckBox を追加。ポストバックして、
  // ユーザーがチェックを入れた項目をサーバー側で取得。
    
  protected void Button1_Click(object sender, EventArgs e)
  {
    string ids = "";
    for (int i = 0; i < ListView1.Items.Count; i++ )
    {
      ListViewItem item = ListView1.Items[i];
      CheckBox cb = (CheckBox)item.FindControl("CheckBox1");
      if (cb != null)
      {
        if (cb.Checked == true)
        {
          ids += ListView1.DataKeys[i].Value.ToString() + " ";
        }
      }
    }
    Label1.Text = "Selected Products: " + ids;
  }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>ListView と CheckBox</title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <asp:Button ID="Button1" 
      runat="server" 
      Text="PostBack" 
      OnClick="Button1_Click" />
    <asp:SqlDataSource ID="SqlDataSource1" 
      runat="server" 
      ConnectionString="<%$ ConnectionStrings:Northwind %>" 
      SelectCommand=
        "SELECT [ProductID], [ProductName], [UnitPrice] 
        FROM [Products] WHERE [CategoryID]=1">
    </asp:SqlDataSource>
    <asp:ListView ID="ListView1" 
      runat="server" 
      DataKeyNames="ProductID" 
      DataSourceID="SqlDataSource1">
      <EmptyDataTemplate>
        <table id="Table1" runat="server" style="">
          <tr>
            <td>
              データは返されませんでした。</td>
          </tr>
        </table>
      </EmptyDataTemplate>

      <ItemTemplate>
        <tr style="">
          <td>
            <asp:CheckBox ID="CheckBox1" 
              runat="server" />
          </td>
          <td>
            <asp:Label ID="ProductIDLabel" 
              runat="server" 
              Text='<%# Eval("ProductID") %>' />
          </td>
          <td>
            <asp:Label ID="ProductNameLabel" 
              runat="server" 
              Text='<%# Eval("ProductName") %>' />
          </td>
          <td>
            <asp:Label ID="UnitPriceLabel" 
              runat="server" 
              Text='<%# Eval("UnitPrice") %>' />
          </td>
        </tr>
      </ItemTemplate>

      <LayoutTemplate>
        <table id="Table2" runat="server">
          <tr id="Tr1" runat="server">
            <td id="Td1" runat="server">
              <table ID="itemPlaceholderContainer" 
                runat="server" 
                border="0" 
                style="">
                <tr id="Tr2" runat="server" style="">
                  <th id="Th1" runat="server">
                    Select</th>
                  <th id="Th2" runat="server">
                    ProductID</th>
                  <th id="Th3" runat="server">
                    ProductName</th>
                  <th id="Th4" runat="server">
                    UnitPrice</th>
                </tr>
                <tr ID="itemPlaceholder" runat="server">
                </tr>
              </table>
            </td>
          </tr>
          <tr id="Tr3" runat="server">
            <td id="Td2" runat="server" style="">
            </td>
          </tr>
        </table>
      </LayoutTemplate>

    </asp:ListView>
  </div>
  <asp:Label ID="Label1" runat="server"></asp:Label>
  </form>
</body>
</html>

Tags: ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar