辺境地に住む主婦で在宅プログラマの悩み

久しぶりの投稿です。
最後に投稿したのが2014年1月だから半年ぶりですねぇ。

年末あたりから消費税対応に始まり、忙しかったです。本当に忙しかったです。゚(゚´Д`゚)゚。
最近になってやっと落ち着いたというか、仕事が途切れました。
休みなしでずっと働いてきたので、少しゆっくりさせてもらうのもいいかもしれません。

暇になるとこれからの仕事の事を考えてしまいます。

在宅でプログラムの仕事をするようになって9年。
関西で在宅のお仕事を見つけるのはけっこう難しいです。
androidも勉強してましたが、関西でandroidの在宅の仕事ってあるんでしょうか!?
私には縁がないのかもしれません。

在宅でお仕事を貰えるお客さまに巡りあっても
.netでwindowsアプリを作るか、asp.netのお仕事が多いです。
仕事の幅が広がらない・・・

このブログはandroidで来られる方が多いですが
在宅で需要のあるPHPに転向しようかと悩んでいます。

辺境地に住む主婦がプログラマを続ける事自体が難しいんでしょうかね・・・(´・ω・`)







ASP.NET EnterキーでSubmitさせないようにする。

前回ASP.NET TextBoxでEnterキーやBackSpaceキーを入力できないようにする。 を書きましたが…
submitを発生させるコントロールってtextboxだけじゃないんですね~
checkboxやらradioでもsubmitが発生して、form内の一番最初に配置しているbuttonのclick処理が走ってしまいます。
全部のコントロールにonKeyPressなんて書いてられないので、ほかの方法で実装します。

以下その方法です。

formにダミーボタンを配置しOnClientClickでsubmitさせないようにし、style="display:none"で非表示にします。
つぎにformタグのdefaultbuttonに作成したダミーボタンを指定します。
これですべてのコントロールでenterキーを押されてもsubmitを無効にすることができます。

マスターページを使用していれば、マスターページに実装するだけで済みます。
<form id="form1" runat="server" defaultbutton="DummySubmitButton">
    <asp:Button ID="DummySubmitButton" runat="server" Text="Button" OnClientClick="return false;" style="display:none"  />
    ・・・以下略
</form>

ASP.NET TextBoxでEnterキーやBackSpaceキーを入力できないようにする。

2014年初の投稿です。
昨年からASP.NETのお仕事が数件ほど続いています。

Webアプリを作っている人にとっては常識なのかもしれませんが、
TextBoxでEnterキーを押すとSubmitされてしまう場合があります。
またReadOnlyなTextBoxでBackSpaceキーを押すと「戻る」ボタンと同じ動きをしてしまいます。

JavaScriptでTextBoxにEnterキーや、ReadOnlyなTextBoxにBackSpaceキーを入力できないようにします。
EnterキーはKeyCode=13、BackSpaceキーはKeyCode=8です。
ReadOnlyな場合はEnterキー、BackSpaceキーを入力できないようにします。
ReadOnlyでない場合はEnterキーのみを入力できないようにします。

JavaScript
function cancelSubmit() {
    if (window.event.srcElement.readOnly == false) {
        if (window.event.keyCode == 13) {
            return false;
        }
    }
    else {
        if (window.event.keyCode == 13 || window.event.keyCode == 8) {
            return false;
        }
    }
}
ReadOnlyでないTextBoxの場合はonKeyPressで処理します。
<asp:TextBox ID="TextBox1" runat="server" onKeyPress="return cancelSubmit();" />
ReadOnlyなTextBoxの場合はonKeyDownで処理します。
<asp:TextBox ID="ReadOnlyTextBox1" runat="server" ReadOnly="True" onKeyDown="return cancelSubmit();" />


コチラの方法の方が楽です↓↓
ASP.NET EnterキーでSubmitさせないようにする。

ASP.NET 繰り返しコントロール内で2つのDropDownListを連携する。

繰り返しコントロール(GridView,DataList,Repeater)などのItemTemplateにDropDownListを二つ配置し
一つ目のDropDownListの選択値によって二つ目のDropDownListのDataSourceを変更する方法です。

DataListのItemTemplateにDropDownListを二つ配置します。

<asp:DataList ID="DataList1" runat="server">
    <ItemTemplate>
        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" />
        <asp:DropDownList ID="DropDownList2" runat="server" />
    </ItemTemplate>
</asp:DataList>

DataListのItemCreatedイベントで一つ目のDropDownListにデータを設定し
DropDownListのSelectedIndexChangedイベントを関連付けます。
Private Sub DataList1_ItemCreated(sender As Object, e As DataListItemEventArgs) Handles DataList1.ItemCreated
    Dim ddl1 As DropDownList = DirectCast(e.Item.FindControl("DropDownList1"), DropDownList)
    With ddl1
        .DataValueField = "Cd"
        .DataTextField = "Name"
        .DataSource = GetDropDownList1Data()
        .DataBind()
    End With

    AddHandler ddl1.SelectedIndexChanged, AddressOf ddl1_SelectedIndexChanged
End Sub

一つ目のDropDownListのSelectedIndexChangedイベントでは
一つ目のDropDownListのParentプロパティからDropDownListItemを取得します。
取得したDropDownListItemからFindControlで二つ目のDropDownListはオブジェクトを探します。
Private Sub ddl1_SelectedIndexChanged(sender As Object, e As EventArgs)
    Dim ddl1 As DropDownList = DirectCast(sender, DropDownList)
    Dim ddl1Cd As Integer = CInt(ddl1.SelectedValue)

    Dim item As DataListItem = DirectCast(ddl1.Parent, DataListItem)

    Dim ddl2 As DropDownList = DirectCast(item.FindControl("DropDownList2"), DropDownList)
    With ddl2
        .DataValueField = "Cd"
        .DataTextField = "Name"
        .DataSource = GetDropDownList2Data(ddl1Cd)
        .DataBind()
    End With
End Sub

ASP.NET CustomValidatorでTextが空のTextBoxを検証する

昨晩からドハマりした。
空のテキストボックスをCustomValidatorで検証したい場合はValidateEmptyTextをtrueにしないといけないのね!
知らなかったよー
<asp:TextBox ID="TextBox1" runat="server" />
<asp:CustomValidator ID="CustomValidator1" runat="server" Display="Dynamic" ValidateEmptyText="true"
 ControlToValidate="TextBox1" ErrorMessage="エラーメッセージ"/>

ASP.NET ModalPopupExtenderでDataGridをポップアップ表示し選択した値を元の画面に設定する

ModalPopupExtenderで検索して来られる方が多いようなので、
自分のために、あなたのために書いておきます。

ポップアップ画面にはグリッドが配置されていて、グリッドで選択したデータの値を
呼び出し元のラベルに表示します。
ついでにグリッドのデータは検索で絞り込みができるようにします。

呼び出し元画面には検索ワードを入れるテキストボックスがあり、
ポップアップ表示ボタンを押すと、ポップアップ画面に検索ワードを渡し、ポップアップ表示します。



文章で説明は面倒なのでコード読んでね。

ではまずポップアップ画面から作成です。
ポップアップ画面は使いまわせるようにユーザーコントロールで作成しました。

ModalPopupSample.aspxのデザイナです。
ModalPopupExtenderの設定に注目です。
<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="PopUp.ascx.vb" Inherits="WebApplication1.PopUp" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>

<asp:Panel ID="pnlPopup" runat="server" BackColor="#C0C0FF">
    <asp:UpdatePanel ID="updPopup" runat="server" UpdateMode="Conditional">
        <ContentTemplate>

            <asp:Button ID="btnDummy" runat="server" Text="" Style="display: none" />

            <asp:ModalPopupExtender ID="modalPopupExtender" runat="server"
                TargetControlID="btnDummy"
                BackgroundCssClass="modalBackground"
                DropShadow="true"
                PopupControlID="pnlPopup"
                PopupDragHandleControlID="pnlTitle"
                CancelControlID="btnCancel" />

            <asp:Panel ID="pnlTitle" runat="server">
                ここにタイトル
            </asp:Panel>
            <div>
                ここに内容
                <br />
                検索条件:<asp:TextBox ID="txtSearch" runat="server"/><asp:Button ID="btnSearch" runat="server" Text="表示" />

                <asp:GridView ID="gvList" runat="server">
                    <Columns>
                        <asp:TemplateField HeaderText="選択">
                            <ItemTemplate>
                                <asp:LinkButton ID="lnkbtnSelect" runat="server" CommandName="select">選択</asp:LinkButton>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="列1">
                            <ItemTemplate>
                                <asp:Label ID="lblCol1" runat="server" Text="Label"></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="列2">
                            <ItemTemplate>
                                <asp:Label ID="lblCol2" runat="server" Text="Label"></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
                <asp:Button ID="btnCancel" runat="server" Text="閉じる" />
            </div>
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Panel>

ModalPopupSample.aspxのコードです。
Public Class PopUp
    Inherits System.Web.UI.UserControl

    ''' <summary>
    ''' ダイアログを閉じたイベントのイベント引数
    ''' </summary>
    ''' <remarks></remarks>
    Public Class ClosedEventArgs
        Public Property Col1Value As String
        Public Property Col2Value As String
    End Class

    ''' <summary>
    ''' ダイアログを閉じた際のイベント
    ''' </summary>
    ''' <param name="arg"></param>
    ''' <remarks></remarks>
    Public Event DialogClosed(arg As ClosedEventArgs)


    ''' <summary>
    ''' ポップアップウインドウを表示
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Show(sArg As String)
        Me.txtSearch.Text = sArg 
        Me.gvList.Visible = True
        If Not String.IsNullOrEmpty(Me.txtSearch.Text) Then
            SetGridData()
        End If
        Me.updPopup.Update()
        Me.modalPopupExtender.Show()
    End Sub

    ''' <summary>
    ''' 表示ボタンClickイベント
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
        Me.gvList.Visible = True
        SetGridData()
        Me.updPopup.Update()
        Me.modalPopupExtender.Show()
    End Sub

    ''' <summary>
    ''' グリッドのRowDataBoundイベント
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub gvList_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvList.RowDataBound
        If e.Row.RowType <> DataControlRowType.DataRow Then
            Return
        End If

        Dim drv As DataRowView = DirectCast(e.Row.DataItem, DataRowView)
        '選択
        Dim args() As String = New String() {drv.Item("col1").ToString(), drv.Item("col2").ToString()}
        Dim lnkbtnSelect As LinkButton = DirectCast(e.Row.FindControl("lnkbtnSelect"), LinkButton)
        lnkbtnSelect.CommandArgument = String.Join(",", args)
        '列1
        Dim lblCol1 As Label = DirectCast(e.Row.FindControl("lblCol1"), Label)
        lblCol1.Text = drv.Item("col1").ToString()
        '列2
        Dim lblCol2 As Label = DirectCast(e.Row.FindControl("lblCol2"), Label)
        lblCol2.Text = drv.Item("col2").ToString()
    End Sub
    
    ''' <summary>
    ''' グリッドのRowCommandイベント
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub gvList_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles gvList.RowCommand
        Me.gvList.Visible = False
        Me.modalPopupExtender.Hide()
        Dim args() As String = e.CommandArgument.ToString.Split(","c)
        Dim eventArgs As New ClosedEventArgs
        eventArgs.Col1Value = args(0)
        eventArgs.Col2Value = args(1)
        RaiseEvent DialogClosed(eventArgs)
    End Sub

    ''' <summary>
    ''' グリッドデータ表示
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub SetGridData()
        'データ取得
        Dim sSearch As String = Me.txtSearch.Text
        Dim tbl As New DataTable
        tbl.Columns.Add(New DataColumn("col1", GetType(String)))
        tbl.Columns.Add(New DataColumn("col2", GetType(String)))
        For idx As Integer = 1 To 10
            tbl.Rows.Add(New Object() {idx.ToString, sSearch & idx.ToString})
        Next

        Me.gvList.DataSource = tbl
        Me.gvList.DataBind()
    End Sub


次に呼び出し画面の作成です。

Default.aspxのデザイナです。
ToolkitScriptManagerを配置し、先ほど作成したPopUpユーザーコントロールを配置します。
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="WebApplication1._Default" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<%@ Register Src="~/PopUp.ascx" TagPrefix="uc1" TagName="PopUp" %>


<!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">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server"></asp:ToolkitScriptManager>
        <div>
            <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
                <ContentTemplate>
                    検索条件:<asp:TextBox ID="txtSearch" runat="server" /><asp:Button ID="btnShowPopup" runat="server" Text="ポップアップ表示" /><br />
                    列1:<asp:Label ID="lblCol1Value" runat="server"/><br />
                    列2:<asp:Label ID="lblCol2Value" runat="server"/><br />
                </ContentTemplate>
            </asp:UpdatePanel>
        </div>
        <uc1:PopUp runat="server" id="PopUp" />
    </form>
</body>
</html>
Default.aspxのコードです。
Public Class _Default
    Inherits System.Web.UI.Page

    Private Sub btnShowPopup_Click(sender As Object, e As EventArgs) Handles btnShowPopup.Click
        'ポップアップ画面の表示
        Me.PopUp.Show(Me.txtSearch.Text)
    End Sub

    Private Sub ModalPopupSample_DialogClosed(arg As PopUp.ClosedEventArgs) Handles PopUp.DialogClosed
        'ポップアップ画面を閉じたとき
        Me.lblCol1Value.Text = arg.Col1Value
        Me.lblCol2Value.Text = arg.Col2Value
        Me.UpdatePanel1.Update()
    End Sub

End Class

説明は以上!!

ASP.NET Global_asaxのApplication_Errorからカスタムエラーページが表示されない

1歳児のお世話をしているとブログを書く時間はないデス。
でも今日はハマったので未来の自分のためにメモです。


Global_asaxのApplication_Errorイベントで
Server.Transferでカスタムエラーページを表示しているのですが
.netのエラーページが表示されてしまい、カスタムエラーページが表示されません。
環境はVS2012,Fw3.5です。
まったく同じコードでもVS2008,Fw2.0ではちゃんと動きます。


こういうのわかりにくいから勘弁してほしい…。

ASP.NETのGlobal_asaxのコードです。
Application_Errorイベントでカスタムエラーページを表示します。
Imports System.Web.SessionState

Public Class Global_asax
    Inherits System.Web.HttpApplication

     Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
        ' エラーの発生時に呼び出されます
        'カスタムエラーページを表示します。
        Server.Transfer("~/CustomError.aspx")
    End Sub

End Class


カスタムエラーページではエラー内容を表示してます。

結論いうと、Loadイベントでエラーを出力した後、Context.ClearError() を呼んであげればちゃんと動きました。
CustomError.aspx
Public Class CustomError
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim ex As Exception
        ex = Server.GetLastError
        If TypeOf ex Is HttpUnhandledException AndAlso ex.InnerException IsNot Nothing Then
            ex = ex.InnerException
        End If

        If ex IsNot Nothing Then
            Me.Label1.Text = ex.GetType.ToString
            Me.Label2.Text = ex.Message
        End If

        Context.ClearError() '<--これが必要。
    End Sub

End Class


web.configです
<system.web>
     <customErrors mode="On"/>
</system.web>