2010年12月26日 星期日

Static Import

昨天看到一行 Import static java.xxx.xx;
google 一下知道, 原來對於程式中使用到某類別的static member
可以透過import達到不需要這樣: class_name.static_member
語法>>
import class's single static member
import static java.lang.Math.PI;
或import class's all static members
import static java.lang.Math.*;

不過import static也不要用太多, 以免降低程式碼的可閱讀性

2009年4月8日 星期三

CSS tip, trick and 10 important things

1. 10 important things:
原文
簡體版
2. tips and tricks:
只有簡體版Orz
另一篇簡體版

2009年4月6日 星期一

在GridView內實現編輯、刪除

如果要在GridView內做到編輯或刪除的動作
有兩種作法:
(1)加入CommandField
(2)加入TemplateField
重點:從一般模式進入Edit要指定EditIndex,而且要執行DataBind()才會進入編輯模式(顯示TextBox)!!如果是用後端餵DataSource的方式,要記得再餵一次!!!

作法大致如下:

(1)加入CommandField

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:CommandField ShowEditButton="True" ShowDeleteButton="True"/>
<asp:BoundField DataField="ProgramName" HeaderText="ProgramName"/>
<asp:BoundField DataField="iconid" HeaderText="iconid"/>
<asp:BoundField DataField="classid" HeaderText="classid"/>
</Columns>
</asp:GridView>

後端要處理GridView的RowEditing、RowCancelingEdit、RowDeleting、RowUpdating等事件
例如:

Protected Sub GridView1_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles GridView1.RowEditing
'指定哪列資料進入EditMode
Me.GridView1.EditIndex = e.NewEditIndex
'宣告一個執行Query DB的 object(自訂class)
Dim DataObjUtil As New DataObjectUtility()
Me.GridView1.DataSource = DataObjUtil.GetDataTable("select programname,iconid,classid from tb_functionmenu", Me.Page)
'完成Bind才會讓該列進入EditMode!
Me.GridView1.DataBind()
End Sub


(2)加入TemplateField

<asp:GridView ID="GrvSPCKC" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField>
<EditItemTemplate>
<asp:Button ID="BtnUpdate" runat="server" Text="更新" CommandName="UpdateRow" CommandArgument="<%# CType(Container,GridViewRow).RowIndex %>" />
<asp:Button ID="BtnCancel" runat="server" Text="取消" CommandName="CancelRow" CommandArgument="<%# CType(Container,GridViewRow).RowIndex %>" OnClientClick="return confirm('確定放棄編輯?');" />
</EditItemTemplate>
<ItemTemplate>
<asp:Button ID="BtnEdit" runat="server" Text="修改" CommandName="EditRow" CommandArgument="<%# CType(Container,GridViewRow).RowIndex %>" />
<asp:Button ID="BtnDel" runat="server" Text="刪除" CommandName="DelRow" CommandArgument="<%# CType(Container,GridViewRow).RowIndex %>" OnClientClick="return confirm('確定刪除?');" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="DFCD" DataField="dfcd" />
<asp:BoundField HeaderText="RVNO" DataField="rvno" />
</Columns>
</asp:GridView>

CommandName目的是為了待會處理RowCommand事件時辨別是Edit、Delete or Cancel
CommandArgument則是為了要知道哪列資料要修改或刪除
後端程式碼則只要處理RowCommand事件
如下:

Protected Sub GrvSPCKC_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GrvSPCKC.RowCommand
'讀取傳入的列編號
Dim TrigerRowIndex As Integer = Convert.ToInt32(e.CommandArgument)
'根據CommandName參數呼叫各別函式處理
Select Case e.CommandName
Case "EditRow"
Me.ChangeToEditMode(TrigerRowIndex)
Case "CancelRow"
Me.CancelEditRow()
Case "DelRow"
Me.DeleteRow(TrigerRowIndex)
Case "UpdateRow"
Me.UpdateRow(TrigerRowIndex)
End Select
End Sub


事實上,
方法(1)使用CommandField也是會觸發RowCommand事件
只不過我們忽略他而已
而且RowCommand事件會比RowEditing、RowCancelingEdit..等事件先被觸發!

2009年3月31日 星期二

以程式方式加入網頁Head


//My first CSS
HtmlLink myCSS = new HtmlLink();
myCSS.Href = "~/somecss1.css";
myCSS.Attributes.Add("rel", "stylesheet");
myCSS.Attributes.Add("type", "text/css");
Page.Header.Controls.Add(myCSS);

//Here comes my second
myCSS = new HtmlLink();
myCSS.Href = "~/somecss2.css";
myCSS.Attributes.Add("rel", "stylesheet");
myCSS.Attributes.Add("type", "text/css");
Page.Header.Controls.Add(myCSS);

//JavaScript!
HtmlGenericControl myJavaScript = new HtmlGenericControl();
myJavaScript.TagName = "script";
myJavaScript.Attributes.Add("type", "text/javascript");
myJavaScript.InnerText = "alert('Hello');";
Page.Header.Controls.Add(myJavaScript);

//view source code
<link href="somecss1.css" rel="stylesheet" type="text/css" /><link href="somecss2.css" rel="stylesheet" type="text/css" /><script type="text/javascript">alert('Hello');</script>


缺點就是原始碼會串成一大串,很醜
如果在每個header元素加入這行:
Page.Header.Controls.Add(new LiteralControl("\r\n"));

這樣source code就會變的美美地:

<link href="somecss1.css" rel="stylesheet" type="text/css" />
<link href="somecss2.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
alert('Hello');
</script>

2009年3月3日 星期二

C++ list sort (以結構的子成員排序)

在「C++標準函式庫」一書中提到,
排序演算法中 sort 不適用於list,因為list不支援隨機存取 iterator,
但 list 提供了一個成員函式 sort( ),預設是以 operator < 對所有元素排列。

list.sort( ) 是以 operator < 為準則,對所有元素排列,
但此功能僅限於 list 所存放的是可比較的單純數值型別,
如果在 list 中所存放的是 programmer 自行定義的結構(如含有 id 與姓名),
則無法使用此函式去排序,
比較好的解法是重載 operator (此方法可用於 class 中),
如此一來便可以 list 中的結構子成員來排序,


#include
#include
using namespace std;

typedef struct data
{
data(int i, string s)
{
id = i;
str = s;
}

bool operator>(const data &data2) const
{
return (id < data2.id);
}

int id;
string str;
} DATA_T;

list d_list;

int main()
{
d_list.push_back(DATA_T(8, string("q1")));
d_list.push_back(DATA_T(2, string("q2")));
d_list.push_back(DATA_T(3, string("q3")));

cout << "Before sort:" << endl;

for(list::iterator iter = d_list.begin(); iter != d_list.end(); ++iter) {
cout << (*iter).id << " " << (*iter).str << endl;
}

d_list.sort(greater());

cout << "After sort:" << endl;

for(list::iterator iter = d_list.begin(); iter != d_list.end(); ++iter) {
cout << (*iter).id << " " << (*iter).str << endl;
}

return 0;
}



另一方法,只可使用於較單純的程式裡,因為不能用在class中,
加入 code 已被覆蓋,所以還是用上面的方法吧:)

2009年2月24日 星期二

Include external Jascript file and CSS style sheet


Include 外部 Javascript檔
重點: (1)script標籤要有close tag!
(2)使用"src"屬性而"非href"!!!


<script type="text/javascript" src="../Script/TreeView.js"></script>


InInclude 外部 CSS檔
重點: (1)link標籤不需close tag!
(2)使用"href"屬性!!!


<link rel=stylesheet type="text/css" href="../CssStyle/UserControl.css"/>

2009年2月21日 星期六

為報表加入參數時的注意事項

一般來說
報表的參數通常用在報表在過濾資料或者查詢資料時
也就是我們把Query database與bind通通交給Crystal Report做
但是如果我們是利用程式手動餵DataTable給ReportDocument
再把這個ReportDocument指為CrystalReportViewer的ReportSource
參數還是可以具體的以"參數欄位"show值在報表上
例如:產生週、月、季報表時,除了基本的報表日期,
我們可以將user前一個步驟給定的週、月、季或年呈現在報表
讓閱讀報表時更明白資料內容。
指定報表參數三步驟
(1)在報表設計(.rpt)建立參數欄位,並拉至報表畫面中

(2)在負責產生報表內容的class檔中,建立一個function設定報表參數,例如:

'paramName=報表參數名稱,與rpt檔中的"參數欄位"相同
'paramValue=報表參數值
Public Sub AddParameter(ByVal paramName As String, ByVal paramValue As String)
Dim ParamField As New ParameterField()
Dim ParamDiscreteValue As New ParameterDiscreteValue()
Dim ParamFields As New ParameterFields()

ParamField.ParameterFieldName = paramName
ParamDiscreteValue.Value = paramValue
ParamField.CurrentValues.Add(ParamDiscreteValue)
ParamFields.Add(ParamField)
'把Show報表的CrystalReportViewer物件的ParameterFieldInfo屬性指定為
'剛建立的ParameterFields物件
Me.RptViewer.ParameterFieldInfo = ParamFields

'release resource
ParamField = Nothing
ParamFields = Nothing
ParamDiscreteValue = Nothing
End Sub

簡單來說報表參數的架構是:
ParameterFields集合物件下包含多個ParameterField
一個ParameterField的CurrentValues屬性(Class ParameterValues)
又是集合多個ParameterValue物件....
(上面我以ParameterDiscreteValue物件表示,因為ParameterValue有兩個子類別:
ParameterDiscreteValue與ParameterRangeValue。)
感覺設定ParameterValue有點麻煩
有ParameterFields、ParameterField
又有ParameterValues、ParameterValue
可以理解報表參數可能不只一個,但是為何Value也要用個集合來放??
用MSDN的例子說明:
假若銷售統計報表有"City"這個參數
想要知道Taipei、Kaohsiung這兩個city的銷售情況時
就可以分別指定兩個ParameterValue物件的Value為Taipei、Kaohsiung.....right?
因為報表參數的設計理念是透過報表執行查詢與過濾資料
如果只是單純呈現參數欄位是比較看不出它的作用的

(3)在設定CrystalReportViewer.ReportSource後執行步驟(2)的function

雖然,根據MSDN說明,在指定ReportSource屬性前要先指定ParameterFieldInfo,
否則會出現要求輸入參數值的畫面。例如:


不過,經過測試後
反而是先指定指定ReportSource屬性再指定ParameterFieldInfo才不會出錯!!!
Ok,如果是WindowForm到這一步已經大功告成了
但是如果你像我一樣是寫web專案
你會發現操作CrystalReportViewer上的tool bar時報表內容會消失
顯然這與web先天無狀態有關
要處理這個問題只好把session搬出來了
我的作法是在設定CrystalReportViewer.ReportSource時
將ReportDocument的資料(DataTable)寫入Session:

Public Sub ConfigReport(ByVal paramRptFileName As String, ByVal paramRptData As DataTable)
Me._ReportDocument = New ReportDocument()
Session("RptFileName") = Me.GetReportPhysicPath(paramRptFileName)
Me._ReportDocument.Load(Session("RptFileName"))
Me._ReportDocument.SetDataSource(paramRptData)
Me.RptViewer.ReportSource = Me._ReportDocument
Me.RptViewer.DataBind()
Session("ReportData") = paramRptData
End Sub

本來想直接把ReportDocument物件寫入session
省掉Load、SetDataSource步驟,可惜失敗...只好用2個session分別記錄DataTable與rpt檔名
然後在page事件中再餵一次報表資料:

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
If IsPostBack Then
If Session("ReportData") IsNot Nothing Then
Me._ReportDocument = New ReportDocument()
Me._ReportDocument.Load(Session("RptFileName"))
Me._ReportDocument.SetDataSource(Session("ReportData"))
Me.RptViewer.ReportSource = Me._ReportDocument
Me.RptViewer.DataBind()
Else
RaiseEvent ReportSessionTimeOut()
End If
End If
End Sub

這裡有個小訣竅
千萬不要寫在PageLoad事件中
否則執行時會有意想不到的結果產生
(我的情況是換頁時頁碼會亂跳!!)