2008年7月28日 星期一

如何輸入多筆後再一起記錄到DataBase

拜讀 AllenKuo所精心製作的教學介紹,實在不忍直接偷貼過來,還請看官移駕到原網站欣賞。他在介紹影片中所使用的是 .Net 1.1 GrideView + CollectionBase 來解,但在後面的留言中提到,.Net 2.0 可以利用泛型的類別來完成他。所以自己也笨笨的練習了一下,並將幾個在實作中出槌的小地方註解了一下。

AllenKuo 教學網址

個人心得筆記網址

泛型排序需求

關鍵字:
序列化,RowDeleting,泛型 List<t> ,排序


2008年7月23日 星期三

Professional ASP.NET 2.0 AJAX


程式碼下載網址:[Wrox]
勘誤表:[Wrox]
作者 Dan Wahlin 的 部落格一 部落格二


這本書在Chapter 4 的範例有許多不正確的地方,可以參考作者程式碼中的範例。

延伸閱讀:
01. 在 Dan 的部落格提到 Silverlight 2.0 蠻不錯的介紹。[網址]
02. 免費的 ASP.Net 2.0 介紹。[網址]
03. Silverlight 2.0 安裝注意事項。[網址]
04. 其他相關 Silverlight 功能介紹。[網址]

處理在 GridView 自定控制項觸發事件無法執行的問題

在GridView裡,常常會透過 ItemTemplate 放一些我們所需要的控制項。舉 DropDownList 為例,我們可能會在這個 DropDownList 裡放兩個值,A 與 B 。假設每次的選擇都會需要觸發 PostBack 以利我們做後續動作,所以除了將這個 DropDownList 的 AutoPostBack 設為 True 之外,還會在 .cs 程式裡寫 :



protected override void OnPreRender(EventArgs e)

{
if (!IsPostBack)
{
gv_coorgcd.DataSource = (DataTable)ViewState["tmpTable"];
gv_coorgcd.DataBind();
}
base.OnPreRender(e);
}

protected void gv_coorgcd_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Control ctl=null;
ctl = e.Row.FindControl("ddl_orgtype");
if (ctl != null)
{
DropDownList ddl_orgtype = (DropDownList)ctl;
ddl_orgtype.SelectedIndexChanged += new
EventHandler(ddl_orgtype_SelectedIndexChanged);
}
}
}

protected void ddl_orgtype_SelectedIndexChanged(object sender, EventArgs e)
{
int rowindex = ((GridViewRow) (((DropDownList) sender ).NamingContainer )).RowIndex;
}

這程式裡隱含了很大的問題,但不容易被發現。從 覆載 OnPreRender( ) 來看,只有在第一次進入這個頁面時,才會去執行 gv (GrideView) 的資料繫結,並執行到 gv_coorgcd_RowDataBound(),也因此為 ddl_orgtype 註冊了 SelectedIndexChanged 事件。

然而,當 USER 觸發下拉清單 ddl_orgtype 觸發了 PostBack 後,這次並不會再執行 gv_coorgcd.DataBind(),也不會註冊 SelectedIndexChanged 事件,所以你會發現,ddl_orgtype_SelectedIndexChanged 根本就不再有機會被呼叫。

要解決這問題,目前有兩個方法,分別介紹一下:

方法一:
比較簡單直接。就是將註冊 ddl_orgtype 的 SelectedIndexChanged 事件,改由 .aspx 去寫,而不是原先的 .cs 。 所以,我們可以在 aspx 中寫入以下的程式:

<asp:GridView ID="gv_coorgcd" runat="server" AutoGenerateColumns="False"
OnRowDataBound="gv_coorgcd_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:DropDownList ID="ddl_orgtype" runat="server" AutoPostBack="true"
OnTextChanged="ddl_orgtype_SelectedIndexChanged" >
<asp:ListItem Text="院內" Value="1" Selected="true"></asp:ListItem>
<asp:ListItem Text="院外" Value="2" ></asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

注意囉!就是 OnTextChanged="ddl_orgtype_SelectedIndexChanged" 。我們直接將這事件註冊在這個物件的預設宣告裡,就不用在 .cs 透過程式動態去新增了。

方法二:
雖然在第二次進入頁面時(IsPostBack)沒有再重新繫結 gv_coorgcd,但卻可以知道這次的 PostBack 是由誰所觸發。我們可以據此來決定後面所要執行的動作。

所以,可以在 OnPreRender( ) 事件加上下面的程式:
protected override void OnPreRender(EventArgs e)
{
if (!IsPostBack)
{
gv_coorgcd.DataSource = (DataTable)ViewState["tmpTable"];
gv_coorgcd.DataBind();
}
else
{
string post_target = Request.Form["__EVENTTARGET"];
if (post_target != null)
{
if (post_target.Contains("ddl_orgtype"))
{
//Do something about ddl_orgtype SelectedIndexChanged
}
}
}
base.OnPreRender(e);
}

透過 Request.Form["__EVENTTARGET"] 就可以取得觸發 PostBack 的始作俑者了。

當然,個人是偏好第一種方法,簡單實用又大方。

2008年7月16日 星期三

最後的演講

摘要:
  • 別忘了準備對別人有利的方案,這樣別人才會更願意跟你打交道。
  • 只要把聰明的人講過的話自己拿來講一遍,就能夠讓自己看起來也很聰明。
  • 專注於當下,不去想未來那些負面的事情。我們如果每天都把時間花在為明天提心吊膽,這樣是沒有幫助的。
  • 有太多人都經常抱怨自己人生中的各種問題。我向來認為,你如果願意把抱怨的力氣拿出十分之一用在解決問題上,一定不免大吃一驚,發現事情原來沒有你想像的那麼糟。
  • 你如果沒有得到你想要的東西,至少得到了經驗。失敗不但是可以接授的,而且經常還是人生不可或缺的要素。
  • 你如果比別人花更多時間工作,那麼你在多做的這些時間裡就會對自己的工作更加精通。這樣一來,你就可能變得更有效率、更有能力,甚至更快樂。付出努力就像是銀行的複利,你獲得的獎賞會累積得很快。
  • 想要什麼東西,開口問就是了。不用怕,獲得肯定答案的機會,一定比你想像的還要頻繁。
  • 布魯克斯定律:一項軟體專案的時程如果已經落後,增加人力只會造成落後程度更嚴重。

在 GridView 的內容呈現三位一撇的樣式

如果在 GridView遇到金錢格式的內容,可以直接在 GrideView 的 裡面直接設定就可完成。只需將上 DataFormatString="{0:#,##0}" HtmlEncode="False"

如果只有設定 DataFormatString 是沒有效果的,所以別忘了加上 HtmlEncode="False"

<asp:BoundField HeaderText="計畫經費(仟元)" DataFormatString="{0:#,##0}" HtmlEncode="False"
DataField="org_ordinaryl_fee2" ></asp:BoundField>

參考網址:網址一

補充[20090422]:
如果是使用 ItemTemplate 且使用 Bind 的方式繫結資料,也可以採用資料格式設定方法。



//取到小數第二位
<ItemTemplate >
<asp:Label ID="lb_estipower" runat="server" Text='<%# Bind("pp_estipower3","{0:#.00}") %>' ></asp:Label>
</ItemTemplate>

在 DataView 裡新增一筆紀錄的方法

在 DataView 裡新增一筆紀錄的方法的範例:


DataView dv_emper = (DataView)ds_emper.Select(new DataSourceSelectArguments());
dv_emper.AllowNew = true;
DataRowView newRow = dv_emper.AddNew();
newRow["pem_id"] = "0";
newRow["pem_emper"] = dv_emper[0]["pp_planer"];
newRow["pem_empdept"] = dv_emper[0]["pp_planer_dept"];
newRow["pem_empext"] = dv_emper[0]["pp_planerext"];
newRow["pem_sign_right"] = dv_emper[0]["pp_sign_right"];
newRow.EndEdit();

避免URL網址後面被亂塞資料

偵測頁面的參數,是否存在惡意程式碼,如: 符號 %

透過 Request.Params.Count 取得畫面所有參數,
這些參數,包含著URL後面所串接的所有資訊。
可以寫個簡單的迴圈,去查每個參數是否包含了惡意程式碼符號。

protected void Button2_Click(object sender, EventArgs e)
{
bool bAlert = false;

StringBuilder str = new StringBuilder();
for (int i = 0; i < Request.Params.Count; i++) { str.Append(string.Format("{1}:{0} ",Request.Params[i].ToString(),i)); if (Request.Params[i].ToString().Contains("%")) bAlert = true; } Label1.Text=str.ToString(); if (bAlert) { Label1.Text = Label1.Text + " 偵測到惡意程式碼!"; } } PS:可以將這判斷方法寫成一個類別,並讓每一個頁面去繼承這個類別。
程式碼參考
特殊字元參考

2008年7月14日 星期一

__doPostBack 出不來?

想要透過 javascript 直接去產生 postback 效果,可以直接呼叫 __doPostBack來完成。但我們有時會發生javascript錯誤:必須要有物件。
這會讓我們很困擾,頁面上有時會自動產生 __doPostBack,有時則不會,是根據心情的嗎!? 網友有提供一個方法,保証可以產生出 __doPostBack ,就是:GetPostBackEventReference( )

舉例說,我的頁面有一個控制項,就用最沒什麼用的 Label 好了,只要在 page_load 事件裡,加上

this.GetPostBackEventReference(this.label_name);

保証會讓你偷笑。

參考網址:網址一

2008年7月8日 星期二

javascript 判斷GridView的資料筆數

GridView的特性,是有值的話,就會 Render 到網頁上,我們就可以用一般的方法去存取它。但如果沒有值,他就不會 Render到網頁上,所以這個物件就會是 NULL。於是,當我們想透過 javascript 去操作時,需要特別去處理沒有值的情況。


<script language="javascript" type="text/javascript">
function CheckItem(obj)
{
 var o = document.getElementById(obj);
 if(o)
 {
  var oCount=o.rows.length;
  alert(oCount);
 }
 else
  alert('No data');


 return false;
}
</script>


//呼叫判斷 GridView 是否有值

Button1.OnClientClick = string.Format("return CheckItem('{0}'); ",
GridView1.ClientID);


如果想要取出 DataGrid的值,可以用下面方法:


alert(document.all.GridView1.rows(1).cells(3).innerText);

參考來源一

參考來源二

參考來源三