July 11, 2009

DropDownList控制項的資料驗証 - 使用RequiredFieldValidator & jQuery Validation Plugin

在設計下拉式選單時,常需要將第一個選項設計成"請選擇xxx",在送出表單前會檢查使用者是否有選擇選單裡的其它選項,我們可以ASP.NET 內建的 RequiredFieldValidator 控制項或是jQuery的Validation Plugin來達到驗証的功能。

1. RequiredFieldValidator
<asp:DropDownList ID="DropDownList" runat="server" DataSourceID="ObjectDataSource" DataTextField="ApplicationName" DataValueField="ApplicationId">
 <asp:ListItem Value="-1">請選擇</asp:ListItem>
 <asp:ListItem Value="選項一之值">選項一</asp:ListItem>
 <asp:ListItem Value="選項二之值">選項二</asp:ListItem>
 <asp:ListItem Value="選項三之值">選項三</asp:ListItem>
</asp:DropDownList>

<asp:RequiredFieldValidator ID="RequiredFieldValidator" runat="server" ControlToValidate="DropDownList" Display="Dynamic" ErrorMessage="請選擇下拉式選單" SetFocusOnError="True" InitialValue="-1"></asp:RequiredFieldValidator>

由以上程式碼片段可以看到,我們設定 RequiredFieldValidator 的InitialValue屬性值與DropDownList的第一個選項"請選擇"之值相同註1。當表單送出時會自動檢查下拉式選單所選選項之值是否與 RequiredFieldValidator 相同,如果相同則表單停止送出。

2. jQuery Validation Plugin
(1) 將"請選擇"選項之值設為空字串
(2) 加入以下code snippet
<script language="javascript" type="text/javascript">
    $(function() {
        $("#<%= this.Form.ClientID %>").validate({
            rules: {
            <%= this.DropDownList.UniqueID %>: {required: true}
            },
            messages:{
            <%= this.DropDownList.UniqueID %>: { required: "請選擇下拉式項單"}
            }
        });
    });
</script>

備註
1.也可將"請選擇"選項之值設為空字串,拿掉 RequiredFieldValidator 的InitialValue一樣能執行驗証

July 9, 2009

當TextBox的ReadOnly屬性為true時,Postback後無法讀取TextBox之值

是的。

Postback之後請改用Request.Form[this.TextBox.UniqueID]取得TextBox之值。或是改用TextBox.Attributes.Add("readonly", "readonly")來設定TextBox為readonly而不直接設定TextBox的ReadOnly屬性


參考
http://west-wind.com/weblog/posts/3939.aspx
http://www.codeproject.com/KB/aspnet/Readonly.aspx
http://www.g9th.com/blog/post/2006/12/Readonly-property-of-Textbox-in-ASPNET.aspx

July 5, 2009

CalendarExtender中文顯示問題

CalendarExtender預設是英文介面。如果要顯示出中文介面,可以將ScriptManager控制項的EnableScriptGlobalizationEnableScriptLocalization兩個屬性設定為true,即可顯示出中文,如下:

不過Pete發現了一個地方好像不太對勁,原來是下方的日期居然是顯示Today字樣,而不是中文"今天"或"今日"。這是怎麼回事?原來在AjaxControlToolkit提供的Binary壓縮檔中,還提供了語系資源檔,而Pete忘了將中文語系資源檔(zh-CHT資料夾)一同放進bin裡,而造成中文顯示不出來的問題。

將中文語系檔加入後,一切就正常了。


July 4, 2009

列舉型別的Description屬性用法

列舉型別的Description屬性是個還不錯的功能,目前小弟將它應用在專案中,取代掉一些原本放在資料庫中較不易變動的列舉資料,以減少一些query與join。

有一列舉型別如下
        enum Family : int
        {
            [Description("爸爸")]
            Father = 0,
            [Description("媽媽")]
            Mother = 1,
            [Description("兄弟")]
            Brother = 2,
            [Description("姐妹")]
            Sister = 3,
            [Description("兒子")]
            Son = 4,
            [Description("女兒")]
            Daughter = 5
        }

經由以下函式可取得列舉值的Description屬性值
 public string GetDescription(Enum value)
 {
   FieldInfo fi = value.GetType().GetField(value.ToString());
   DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
   return attributes.Length > 0 ? attributes[0].Description : value.ToString();
 }
  1. 經由列舉值取得Description之值
    GetDescription(Family.Brother)
     
  2. 經由字串值取得Description之值
    GetDescription(((Family) Enum.Parse(typeof(Family), "Brother")))
     
  3. 經由列舉型別的基底型別數值取得Description之值
    GetDescription((Family) Enum.ToObject(typeof(Family), 2))
備註
1.使用時需引入System.ComponentModelSystem.Reflection
2.可將此函式改寫為Extension Methods增加使用上的方便性,或參考國外網友使用泛型來達到相同效果

其它參考
http://www.moggoly.me.uk/blog/post/Enum-description-values.aspx
http://blogs.freshlogicstudios.com/Posts/View.aspx?Id=388f7d39-0b90-43bc-b03a-c1f605dfb499

Object.ToString()與Convert.ToString()

當需將物件轉換成字串我們最常使用Object.ToString()來取得轉換後的結果。但當Object是null時,系統就會丟出NullReferenceException,因為我們不能將null轉換成字串。常見的情況發生於讀取資料庫欄位資料時,如果欄位設定為nullable,當我們在程式碼中嘗試用DataReader["ColumnName"].ToString()去讀出字串資料時,就有可能會出NullReferenceException。
解決的方法有幾個:
  1. 先對DataReader["ColumnName"]做null checking,再根據結果做ToString()或回傳空字串(或其它有意義的字串)。
     
  2. 永遠將欄位設為有預設值(如空字串或其它數值資料)而不要允許null欄位
     
  3. 使用Convert.ToString()來做轉換
ToString()預設是為沒有做null checking的,而Convert.ToString()會在轉換字串時先對要轉換的物件做null checking。我們可以由 .NET Reflector 這套工具看出,如果物件為null的話Convert.ToString()就會回傳空字串,如下:

        public static string ToString(object value, IFormatProvider provider)
        {
            IConvertible convertible = value as IConvertible;
            if (convertible != null)
            {
                return convertible.ToString(provider);
            }

            IFormattable formattable = value as IFormattable;

            if (formattable != null)
            {
                return formattable.ToString(null, provider);
            }

            if (value != null)
            {
                return value.ToString();
            }

            return string.Empty;
        }

以執行速度來說,根據Brad Abrams的測試,ToString()會比Convert.ToString()快些,由上面的程式碼可以知道為什麼。因為少了null checking。

結論
當不確定所轉換的物件是否為null時,可以用Convert.ToString()來做轉換,以避免系統拋出例外訊息;當確定物件不為null時,直接使用ToString()即可。