|
|
2008年6月22日
摘要: 摘要之前在「Calendar 动态产生子控件的 Event Handler」一文中有提到如何处理 Calendar 在 DayRender 事件动态产生按钮的事件处理,文中最后有提及,若 Calendar 控件有类似 GridView 控件中有 RowCommand 事件,在使用上就可以更简化。所以本文将扩展 Calendar 控件,新增 DayCommand 事件,就动态产生的按钮可以可以引发 ... 阅读全文
2008年6月21日
2008年6月18日
若要计算二个日期经过几月又几天,需要考虑期间每个月份的天数,每个月的天数是不一样的。
所以我们可以先计算经过几个月,然后把起始日期累加异差月份数,再计算差异天数。
Dim oDate1 As Date = Date.Parse("2008/5/1")
Dim oDate2 As Date = Date.Parse("2008/7/10")

'先算月份
Dim iMonths As Integer = DateDiff(DateInterval.Month, oDate1, oDate2)
'再算天数
Dim iDays As Integer = DateDiff(DateInterval.Day, DateAdd(DateInterval.Month, iMonths, oDate1), oDate2)

MsgBox(String.Format("经过{0}月{1}天", iMonths, iDays))
2008年6月17日
我们常用 Hashtable 来描述索引键/值组的集合,Hashtable 的键值是区分大小写的。
Dim oHash As New Hashtable()
Dim bIsFind As Boolean

oHash.Add("A", "ValueA")
oHash.Add("B", "ValueA")
oHash.Add("C", "ValueA")

bIsFind = oHash.Contains("a") '鍵值 "a" 不存在
bIsFind = oHash.Contains("A") '鍵值 "A" 存在
若我们需要让 Hasktable 不区分大小写怎么处理呢?常看到的一种作法就是在 Hasktable 的加入/移除时先将键值全转为小写(或大写),而判断时也将键值同样转为小写(或大写)。
Dim oHash As New Hashtable()
Dim bIsFind As Boolean

oHash.Add("A".ToLower, "ValueA")
oHash.Add("B".ToLower, "ValueA")
oHash.Add("C".ToLower, "ValueA")

bIsFind = oHash.Contains("a".ToLower) '鍵值 "a" 存在
bIsFind = oHash.Contains("A".ToLower) '鍵值 "A" 存在
当然上述的方式是可行为,不过略显麻烦,若键值忘了转换就加入就容易导致找不到的情形,最好的方式就是由 Hashtable 本身自行处理,让开发人员无需去理会键值大小写。
在 Hasktable 的有一多载的建构函式如下
 Public Sub New()Sub New ( _
equalityComparer As IEqualityComparer _
)
所以我们只要撰写一个具 IEqualityComparer 接口的类别来做键值比对就可以了。
 Public Class THashKeyComparerClass THashKeyComparer
Implements IEqualityComparer

 Public Function Equals1()Function Equals1(ByVal x As Object, ByVal y As Object) _
As Boolean Implements IEqualityComparer.Equals
Return (CStr(x).ToLower = CStr(y).ToLower)
End Function

 Public Function GetHashCode1()Function GetHashCode1(ByVal obj As Object) _
As Integer Implements IEqualityComparer.GetHashCode
Return obj.ToString().ToLower().GetHashCode()
End Function
End Class
当我们要使用 Hasktable 时,只要使用自定义具 IEqualityComparer 的类别来初始化 Hasktable 即可。

Dim oHash As New Hashtable(New THashKeyComparer())
Dim bIsFind As Boolean

oHash.Add("A", "ValueA")
oHash.Add("B", "ValueA")
oHash.Add("C", "ValueA")

bIsFind = oHash.Contains("a") '鍵值 "a" 存在
bIsFind = oHash.Contains("A") '鍵值 "A" 存在
2008年6月13日
2008年6月12日
2008年6月11日
摘要
使用 SqlDataSource 控件可以很方便的与 UI 控件 (如 GridView、FormView) 系结来呈现数据,若需要针对 SqlDataSource 做数据筛选时,最直觉的方式就是去修改 SqlDataSoruce.SelectCommand 的 SQL 命令来执行数据筛选,这样设定的呈现结果感觉是正确的,数据真得依设定的条件来筛选过滤。可以当 UI 控件重新做 DataBind 时,如 GridView 换页的动作,会发生数据又全部跑出来了。为何会有这样异常的结果呢?本文就是来说明发生这种情形的原因及正确的程序撰写方式。
SqlDataSource 执行数据筛选
在页面上放置 SqlDataSource 及 GridView 来呈现数据,并将 GridView 设定分页,页面控件的配置如下所示,当按下 [Filter] 按钮时,会依选取的字段名称及输入的筛选值来过滤数据。

在 [Filter] 按钮的 Click 事件撰写如下程序代码,主要是依设定的字段及筛选值产生 SQL 语法,并设定给 SqlDataSource.SelectCommand 属性。
 Protected Sub btnFilter_Click()Sub btnFilter_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnFilter.Click
Dim sSQL As String
Dim sFilter As String

Select Case ddlFile.SelectedValue.ToUpper
Case "EmployeeID".ToUpper
sFilter = "[EmployeeID]=" & txtValue.Text
Case Else
sFilter = "[" & ddlFile.SelectedValue & "] Like '%" & txtValue.Text & "%'"
End Select

sSQL = "SELECT [EmployeeID], [LastName], [FirstName], [Title], [City] FROM [Employees] Where " & sFilter
SqlDataSource1.SelectCommand = sSQL
End Sub
在 [DataBind] 按钮的 Click 事件撰写如下程序代码,主要是在显示 SqlDataSource.SelectCommand 属性值及执行 GridView.DataBind,使 GridView 重新系结数据。
 Protected Sub btnDataBind_Click()Sub btnDataBind_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDataBind.Click
Response.Write("SelectCommand: " & SqlDataSource1.SelectCommand)
GridView1.DataBind()
End Sub
执行程序,选择 EmployeeID 字段,输入筛选值为 "3",按下 [Filter] 按钮来执行筛选,执行结果可以正确筛选资料。

可是这时我们按下 [DataBind] 按钮,让 GridView 重新做数据系结。这时发生了奇怪的现象,资料怎么全又跑出来了呢?仔细看一下输出的 SqlDataSource.SelectCommand 属性值,它怎么不是我们刚刚设定的筛选 SQL 语法呢?若筛选的数据可以分页,你会发现按换页的结果,也会发生同样的情形,因为 换页也需要 DataBind,所以跟自行去设定 DataBind 的结果是一样的。

为什么设定的 SelectCommand 属性值不见了呢?主要原因就是 SelectCommand 属性并没有被保留在 ViewState 中,所以每次 PostBack 时,它的值就会还原为设计阶段的初始值。
SqlDataSource 执行数据筛选正确作法
即然我们知道原因是「SelectCommand 属性并没有被保留在 ViewState 中」,那最简单的方式就是我们自行撰写程序将其保留在 ViewState 中,故页面覆写 LoadViewState 及 SaveViewState 方法来保留 SelectCommand 属性。
 /**/''' <summary>
''' 由 ViewState 还原控件的状态。
''' </summary>
''' <param name="savedState">要还原的控件状态。</param>
 Protected Overrides Sub LoadViewState()Sub LoadViewState(ByVal savedState As Object)
If Not (savedState Is Nothing) Then
' Load State from the array of objects that was saved at ;
' SavedViewState.
Dim myState As Object() = CType(savedState, Object())

If Not (myState(0) Is Nothing) Then
MyBase.LoadViewState(myState(0))
End If

If Not (myState(1) Is Nothing) Then
SqlDataSource1.SelectCommand = CType(myState(1), String)
End If
End If
End Sub

 /**/''' <summary>
''' 控件的状态储存至 ViewState。
''' </summary>
''' <returns>含有控件之目前检视状态的对象。</returns>
 Protected Overrides Function SaveViewState()Function SaveViewState() As Object
Dim baseState As Object = MyBase.SaveViewState()
Dim myState(1) As Object
myState(0) = baseState
myState(1) = SqlDataSource1.SelectCommand
Return myState
End Function
重新执行程序,与之前的做法一样来筛选数据,最后按下 [DataBind] 按钮重新做数据系结,可以发现结果正确了,而输出的 SelectCommand 属性值也是我们最后设定的值。

2008年6月10日
摘要: 摘要若窗体(页面)具有「执行、新增、修改、删除」等操作权限控管,可以使用列举来描述使用者在该窗体的权限,详细的作法可以参考下面的「Enum 的设计与应用 - 简易权限设计」这篇文章。在此我们将利用这种列举的方式来描述窗体权限,并由 BasePage 来处理窗体权限的控管。程序说明及实作首先定义 EFormActions 列举,来描述窗体操作权限。/**/'''<summary>'''窗... 阅读全文
2008年6月6日
摘要
在 ASP.NET 中,ObjectDataSoruce 控件是实现三层式的重要关键,我们可以透过 ObjectDataSoruce 控件使用的自订中间层商务对象。不过一般找到的范例都是直接系结中间层商务对象,虽然范例通常写得相当符合对象导向,可是在实际运用上有下列几个问题。
问题一:维护性不佳
例如 Employee 商务对象的 Update 方法,可能有下列二种写法
[写法一] Update 方法中,每个字段皆为自变量
Public Function UpdateEmployee(EmployeeID As Integer, LastName As String, FirstName As String, _
Address As String, City As String, Region As String, _
PostalCode As String) As Integer
参考:http://msdn.microsoft.com/zh-tw/library/ms178538(VS.80).aspx
[写法二] Update 方法使用强型别,每个字段对应到类别的属性
Public Function UpdateEmployee(employee As NorthwindEmployee) As Integer
参考:http://msdn.microsoft.com/zh-tw/library/ms227562(VS.80).aspx
可是实际上真能这样用吗?以[方法一]为例,若异动字段非常多,Update 方法的自变量不就多到吓死人;[方法二]使用强型别可以解决字段多的问题,不过字段增减时,都需要同时维护 NorthwindEmployee 类别不是很麻烦吗?当你的系统非常庞大时,例如有上千个窗体,当这些窗体若需同时新增一个字段时,那就需要同时更新上千个对应的类别,可能会搞到你疯掉。
问题二:批次异动问题
当 GridView |