| OS | Windows Vista |
| VisualStudio | 2005 + Vistaパッチ |
| .NET | 2.0 |
| ブラウザ | IE7 |
| 言語 | VB.NET |
<%@ Master Language="VB" CodeFile="SampleMasterPage.master.vb" Inherits="MasterPage" %>
<!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 id="Header" runat="server">
<title>サンプルマスタページ</title>
<link rel="stylesheet" href="default.css" type="text/css" media="all" />
</head>
<body>
.
.
.
ヘッダタグにidを追加.(原文はコードがC#)
Contents.aspx.vb(コンテンツページのコードビハインドファイル)
protected Sub Page_Load(object sender, EventArgs e)
Dim literal As Literal = new Literal()
literal.Text = "<link rel='stylesheet' type='text/css' href='StyleSheet.css' />"
Dim hh As HtmlHead = DirectCast(Page.Master.FindControl("Header"),HtmlHead)
hh.Controls.Add(literal);
End Sub
マスタページは,Page.Masterでアクセスできるので,そこにリテラルを追加.<asp:TemplateField HeaderText="選択"> <ItemTemplate> <asp:CheckBox ID="chkProc" runat="server" /> </ItemTemplate> </asp:TemplateField>
' IDがSampleGridViewのGridViewのTemplateField内に
' IDがchkProcのCheckBoxが配置されているとします
Public Function getCheckedRows() As DataRow()
Dim result As New List(Of DataRow)()
' 全行を対象にする
For Each line As GridViewRow In Me.SampleGridView.Rows
' ヘッダやフッタは対象外
If line.RowType = DataControlRowType.DataRow Then
' 行内のチェックボックスを取得
Dim checkbox As CheckBox = DirectCast(line.FindControl("chkProc"), CheckBox)
' チェックが入っていたなら,その行と関連づけられているDataRowを取得
If checkbox.Checked = True Then
lines.Add(DirectCast(line.DataItem, DataRowView).Row)
End If
End If
Next
' 配列として返す
Return result.ToArray()
End Function
非常にシンプルです.lines.Add(DirectCast(line.DataItem, DataRowView).Row)この部分を変えることでどんな風にでもできます.
<asp:TemplateField HeaderText="お天気"> <ItemTemplate> <asp:Label ID="lblWEATHER" runat="server" /> </ItemTemplate> </asp:TemplateField>GridViewのRowDataBoundイベントを利用すると,
#{' RowDataBoundイベント}
Protected Sub SampleGridView_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles SampleGridView.RowDataBound
#{' e.Rowには,対象となるGridViewの行が入っています}
Dim line As GridViewRow = e.Row
#{' イベントが発生するのは,DataSourceと結び付いた直後なので,このようにしてデータを取り出せます}
Dim row As DataRow = DirectCast(line.DataItem, System.Data.DataRowView).Row
#{' 値によって表示をわける}
Select Case row.Item("SAMPLE_NUMBER")
Case 1
DirectCast(line.FindControl("lblWEATHER"), Label).Text = "晴天"
Case 2
DirectCast(line.FindControl("lblWEATHER"), Label).Text = "雨天"
End Select
End Sub
ちなみにこれ,row.Item("SAMPLE_NUMBER")がDbNullだったら多分落ちます.*1 : この程度なら,SQL文を工夫すれば普通に表示できますが例なので
*2 : もちろんサーバサイドで使ってもいいですし
<%@ Register TagPrefix="タグ接頭辞" TagName="タグ名" Src="Webユーザーコントロールへのパス(相対パスと絶対パスどちらでもOK)" %>実際は次のような感じ.
<%@ Page Language="VB" MasterPageFile="~/SampleMasterPage.master" AutoEventWireup="false" CodeFile="sample.aspx.vb" Inherits="sample" title="サンプルページ" %> <%@ Register TagPrefix="uc" TagName="SampleWebUserControl" Src="~/SampleWebUserControl.ascx" %> <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> <uc:SampleWebUserControl runat="server" ID="sample" /> </asp:Content>このように,<TagPrefix:TagName ~ />といった感じで使います.
<asp:Label runat="server" Text="ラベルに表示する文字列" ID="sample" />ユーザーコントロールで次のようにLabelと同じことをするにはどうするか.
<uc:SampleWebUserControl runat="server" ID="sample" sampleField="5" />@IT:.NET TIPS [ASP.NET]ユーザー・コントロールで属性を設定するには? - C# VB.NET Webフォーム
Protected _foo As Integer Public WriteOnly Property foo() As Integer Set(ByVal value As Integer) Me._foo = value End Set End PropertyWriteOnlyである必要はありませんが,値をセットするだけならGetterは必要無いので.
| Validator種別 | 概要 |
|---|---|
| RequiredFieldValidator | 必須チェック |
| RangeValidator | 数値の範囲チェック |
| RegularExpressionValidator | 正規表現チェック |
| CompareValidator | 数値の比較チェック |
| CustomValidator | ユーザが処理内容を定義できるValidator |
// 文字列長をチェックするValidator
function customValidator_StringLength(source, arguments) {
var val = arguments.Value;
if (val == "") {
arguments.IsValid = true;
return;
}
var len = 0;
var c;
for (i = 0; i < val.length; i++) {
c = escape(val.charAt(i));
}
if(c.length > 3) {
//len += 2;
len += 1;
} else {
len += 1;
}
// CustomValidatorオブジェクトのcontroltovalidateフィールドで検証対象のIDを取得している.
// ここでは,検証対象(<input type="text"などを想定)のmaxlengthを許可文字列長の閾値としている.
var limit = document.getElementById(source.controltovalidate).maxLength;
if (len <= limit) {
arguments.IsValid = true;
} else {
arguments.IsValid = false;
}
}
arguments.Valueに入力値が入っているので,この値に対して何らかの検証を行い,' 文字列長の検証 Protected Sub customValidator_StringLength(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) ' ここでもJavaScriptと同じように検証対象のMaxLengthから許容文字列長を取得している Dim limit As Integer = DirectCast(Me.FindControl(source.ControlToValidate), TextBox).MaxLength If limit >= args.Value.Length Then args.IsValid = True Else args.IsValid = False End If End SubJavaScriptと同じく,第二引数のIsValidにTrueを設定すれば検証OK,Falseを設定すれば問題ありとなります.
<asp:TextBox ID="txtSample" runat="server" MaxLength="30"/> <asp:CustomValidator ID="sampleCutomValidator" runat="server" ClientValidationFunction="customValidator_StringLength" OnServerValidate="customValidator_StringLength" ErrorMessage="文字列が長すぎます" ControlToValidate="txtSample" />
ボタンをクリック→Validatorによって入力チェック→確認ダイアログを出す(OK/キャンセル)→OKならsubmitという流れを想定するとします.
OnClientClick="if (confirm('登録します.よろしいですか?') == false) return false;"
しかし,実はこれだと次のようになってしまいます.ボタンをクリック→確認ダイアログを出す(OK/キャンセル)→Validatorによって入力チェック→OKならsubmitこれを回避するには,自力で上の処理を書く必要があります.
OnClientClick="if (Page_ClientValidate('mainGroup')) { if(confirm('登録します.よろしいですか?') == false) return false; }"
'mainGroup'には,検証対象のValidationGroupを指定して下さい.
if ( (function(){ return confirm('登録します.よろしいですか?');})() == false ) return false;
*3 : Webフォーム固有の問題というわけではないですが,構築するシステムの多くが個人情報を扱うデータベースと連携していたりしている上に入力項目が非常に多くて実装が大変かつ不具合が混入しやすく,しかも狙われやすかったりと大きな問題です.
//ユーザーコントロールに公開メソッドを追加 Public Sub registerValidator(ByRef sourceValidator As CustomValidator) // validationTargetControlは,検証対象のコントロール sourceValidator.ControlToValidate = Me.validationTargetControl.ID // Validatorコントロールを検証対象のコントロールの次に追加 Me.Controls.AddAt(Me.Controls.IndexOf(Me.validationTargetControl) + 1, sourceValidator) End Subユーザーコントロールを使う側に次のような処理を追加します.
//変数名 Validator: "sampleValidator" ユーザーコントロール: "sampleUserControl" //ユーザーコントロールに追加するValidator Dim sampleValidator As New CustomValidator() //通常のVaildatorと同じように検証用の設定をする sampleValidator.ID = "sampleValidatorID" sampleValidator.ErrorMessage = "<br />検証結果が不正です" sampleValidator.ClientValidationFunction = "customValidator_Function" sampleValidator.ValidationGroup = "SampleValidationGroup" sampleValidator.EnableClientScript = True sampleValidator.Enabled = True sampleValidator.Visible = True //サーバーサイドの検証メソッドを関連づける AddHandler sampleValidator.ServerValidate, AddressOf Me.customValidator_Function //ユーザーコントロールにValidatorを追加 Me.sampleUserControl.registerValidator(sampleValidator)
objParam.Value = DbNull次のようにすればOK
objParam.Value = DbNull.Value
' SQL文の作成
sql += "UPDATE SAMPLE"
sql += " SET "
sql += " FOO = #{@FOO}"
sql += " ,BAR = #{@BAR}"
sql += " WHERE FOOBAR = #{@FOOBAR}"
' コマンドをセット
objCommand.CommandText = sql
' パラメータをセット
objParam = objCommand.CreateParameter()
objParam.ParameterName = "@FOO"
objParam.Value = True
objParam.DbType = Data.DbType.Boolean
objCommand.Parameters.Add(objParam)
objParam = objCommand.CreateParameter()
objParam.ParameterName = "@TO_PAYMENT_DATE"
objParam.Value = "対応する値"
objParam.DbType = String
objCommand.Parameters.Add(objParam)
objParam = objCommand.CreateParameter()
objParam.ParameterName = "@FOOBAR"
objParam.Value = id
objParam.DbType = Data.DbType.Int32
objCommand.Parameters.Add(objParam)
で,このDbCommandをDB接続オブジェクトに渡すとクエリが発行できるというわけです.sql += "UPDATE T_ORDERS" sql += " SET " sql += " TO_PAYMENT_FLAG = 'True'" sql += " ,TO_PAYMENT_DATE = '対応する値'" sql += " WHERE TO_ID = '" + id.toString() + "'"行数はこっちのが少なくて見通しが良さそうですが,
SELECT FOO + BAR AS FOOBAR, FOO, BAR FROM SAMPLE文字列結合には+演算子を使います.
現在のセッションの CONCAT_NULL_YIELDS_NULL の設定を変更することにより、この動作を変更できます。しかし,設定まで変えなくても次のようにすることで回避可能です.
SELECT #{ISNULL(FOO,'')} + BAR AS FOOBAR, FOO, BAR
FROM SAMPLE
ISNULL関数は,第一引数に対象の列名を取り,この列の値がNULLだった場合に第二引数の値を返します.