此篇文章受密碼保護,請輸入密碼後閱讀。
- 8月 13 週一 201213:34
2012/08/13 給未來的我
- 6月 20 週三 201215:37
[ASP.NET]【轉貼】WebUserControl之間值得傳遞(使用Interface)
本文轉貼於 WebUserControl之間值得傳遞(使用Interface)
緣起
在使用WebUserControl的時候,如果一個畫面有數個WebUserControl的話,他們彼此間要怎麼溝通呢,也許有人說,使用FindControl/Property啊!!的確,小喵以前是這樣處理的,不過小喵卻發現這會讓WebUserControl在程式撰寫上變得複雜,既然要寫成WebUserControl,就是要把這些東西抽出來獨立處理/重複使用。但是如果寫的過程讓他與別的東西關係太密切,那就失去了抽出獨立處理/重複使用的目的。
再一次偶然的機會與熱心的Allen大聊到了物件(物件小喵一直都還在學),Allen大十分熱心的提示小喵可以用Interface來解決這類的問題。後來小喵在Allen大的文章也找到相關的範例與影片教學。不過範例是C#的,小喵用VB.NET來說明一次。
兩種模式
這邊會介紹兩種方式,都是透過Interface來處理:
訂閱者模式:定義發行者(Publisher)與讀者(Reader)這兩種Interface處理
事件模式:定義一個Event來丟資料,然後由Reciver來承接事件丟出的資料並且處理
Allen大的範例與教學檔如下,有興趣的人或者是學C#的人可以到Allen大的網站上查看:
範例:MasterPage, Page, UserControl 如何互動, 傳值(事件模式)
教學影片:如何做到 User control 互動-觀察者模式(觀察者模式)
準備WebUserControl畫面
接著小喵分別描述一下使用這兩種方式的範例:兩個範例的動作是一樣的,只是使用不同的方式處理。範例中使用北風資料庫,分別有三個WebUserControl
選擇Employee的下拉式選單:wucGetEmployee.ascx
顯示某Employee的Orders:wucEmpOrder.ascx
顯示某筆Order的Detail資料:wucOdrDetails.ascx
這三個的畫面分別如下
wucGetEmployee.ascx
--
wucEmpOrder.ascx
--
wucOdrDetails.ascx
兩種模式會用到的WebUserControl是一樣的,可以複製一份到另一個資料夾,以備等一下使用
接著就要開始來使用,兩種模是從這裡起會有不同的內容,以下分別說明
觀察者模式
首先先幫觀察者模式建立Interface,相關程式碼如下
接著,一個一個的wuc來處理囉!!
首先是wucGetEmployee.ascx,這個wuc是個發行者。他選了某個Employee後,把EmployeeID發行出去,至於訂閱者收到Employee之後,要做什麼事情,這個跟目前的wucGetEmployee.ascx沒關係,那是別人的事情。
所以我們要在wucGetEmployee.ascx的CodeFile中Implements 這個Interface
此時會在畫面中自動多出一段程式碼,這是配合Implements IPublisher的原因
接著安排一個本頁的全域變數m_Orders,用這個來記錄有哪些訂閱者,訂閱了這個wuc
再來,我們在剛剛的Regorder中,加上要註冊訂閱者的程式碼
另外,這個下拉式選單,結合資料庫後,希望多出一筆請選擇。最後,希望在DropDownList的SelectedIndexChanged時,可以通知每一個訂閱者目前的EmployeeID
這樣就完成的這個發行者wucGetEmployee.ascx的部分。
接著,撰寫wucEmpOrder.ascx的部分,對於wucGetEmployee.ascx來說,他是訂閱者(觀察者)所以一開始的時候,先在後端CodeFile加入Implements IOrder,因為Implements了IOrder,畫面會順便帶出ProcessData的部分
我們希望他訂閱到資料後,將得到的EmployeeID給畫面中的SqlDataSouce於是程式碼
事實上,wucEmpOrder.ascx他不只是個訂閱者,對OrderDetail來說他也是個發行者,希望選擇GridView裡面的Order之後,就顯是相對應的OrderDetail
過程與上面相似,就不贅述...詳細程式內容請參考本文最後面的範例檔。
最後把這兩個wuc放到畫面後,還需要處理一些些程式。
我們先把這三個wuc拉到畫面中,畫面如下
註冊上去後,他們彼此的關係還沒有設定,因此我們在PageLoad事件中,直行發行者的RegOrder來註冊訂閱者
這樣在PageLoad的時候,wucGetEmployee1知道了wucEmpOrder1訂閱了他,wucEmpOrder1也知道了wucOdrDetails1訂閱了他。
事件模式
上面說明了觀察者模式後,接著說明事件模式。這兩個模是要做的事情是一樣的,不過裡面運作的概念上卻不太相同。這裡改以觸發事件的方式來處理。
一樣的先撰寫需要的Interface,首先建立一個類別,清除類別的程式碼,改成這樣
設定好後,接著一樣的,先從源頭的wucGetEmployee.ascx開始撰寫起
一樣的,先幫這個wuc的CodeFile安排Implements IEventMode此時會自動產生一個Event的語法
接著,在DorpDownList的SelectedIndexChanged事件中,要去觸發這個事件,並且將目前的SelectedValue透過事件傳出去
接著安排wucEmpOrder.ascx這個,對於這個而言,當wucGetEmployee.ascx觸發了事件後,他要透過Reciver的UseData把事件中的值給予SqlDataSouce,一樣的要先Implements IReciver介面
而對於此wuc他不只是Reciver也是EventMode因此也要Implements IEventMode介面,這部分與上面一樣,就不贅述了。
最後要把三個wuc放在畫面上,並且在aspx的CodeFile要處理一下,當三個wuc放到畫面後,畫面並不知道事件觸發應該要影響其他哪些wuc,因此要撰寫SetOrderData與SetOrderDetail這兩個Sub來通知Reciver開始使用事件發生的資料相關的程式碼如下(這部分與C#的程式碼差異度較大,如果是C#的使用者請參考Allen大的範例)
最後小喵將相關程式碼壓縮在此
請下載參考
http://vip2.blueshop.com.tw/topcat/DEMO/UC2UC/UC2UC.zip
緣起
在使用WebUserControl的時候,如果一個畫面有數個WebUserControl的話,他們彼此間要怎麼溝通呢,也許有人說,使用FindControl/Property啊!!的確,小喵以前是這樣處理的,不過小喵卻發現這會讓WebUserControl在程式撰寫上變得複雜,既然要寫成WebUserControl,就是要把這些東西抽出來獨立處理/重複使用。但是如果寫的過程讓他與別的東西關係太密切,那就失去了抽出獨立處理/重複使用的目的。
再一次偶然的機會與熱心的Allen大聊到了物件(物件小喵一直都還在學),Allen大十分熱心的提示小喵可以用Interface來解決這類的問題。後來小喵在Allen大的文章也找到相關的範例與影片教學。不過範例是C#的,小喵用VB.NET來說明一次。
兩種模式
這邊會介紹兩種方式,都是透過Interface來處理:
Allen大的範例與教學檔如下,有興趣的人或者是學C#的人可以到Allen大的網站上查看:
範例:MasterPage, Page, UserControl 如何互動, 傳值(事件模式)
教學影片:如何做到 User control 互動-觀察者模式(觀察者模式)
準備WebUserControl畫面
接著小喵分別描述一下使用這兩種方式的範例:兩個範例的動作是一樣的,只是使用不同的方式處理。範例中使用北風資料庫,分別有三個WebUserControl
這三個的畫面分別如下
wucGetEmployee.ascx
1 | <asp:DropDownList ID="ddlEmployee" runat="server" AutoPostBack="True" |
2 | DataSourceID="sdsEmployeeID" DataTextField="EmpName" |
3 | DataValueField="EmployeeID"> |
4 | </asp:DropDownList> |
5 | <asp:SqlDataSource ID="sdsEmployeeID" runat="server" |
6 | ConnectionString="<%$ ConnectionStrings:NWind %>" |
7 | SelectCommand="SELECT EmployeeID, CONVERT (varchar(10), EmployeeID) + '-' + LastName AS EmpName FROM Employees ORDER BY EmployeeID"> |
8 | </asp:SqlDataSource> |
--
wucEmpOrder.ascx
01 | <asp:GridView ID="gvEmpOrder" SkinID="GV01" runat="server" AllowPaging="True" |
02 | AutoGenerateColumns="False" DataKeyNames="OrderID" DataSourceID="sdsOrders"> |
03 | <Columns> |
04 | <asp:CommandField ShowSelectButton="True" /> |
05 | <asp:BoundField DataField="OrderID" HeaderText="OrderID" InsertVisible="False" |
06 | ReadOnly="True" SortExpression="OrderID" /> |
07 | <asp:BoundField DataField="CustomerID" HeaderText="CustomerID" |
08 | SortExpression="CustomerID" /> |
09 | <asp:BoundField DataField="EmployeeID" HeaderText="EmployeeID" |
10 | SortExpression="EmployeeID" /> |
11 | <asp:BoundField DataField="OrderDate" HeaderText="OrderDate" |
12 | SortExpression="OrderDate" /> |
13 | <asp:BoundField DataField="Freight" HeaderText="Freight" |
14 | SortExpression="Freight" /> |
15 | <asp:BoundField DataField="ShipName" HeaderText="ShipName" |
16 | SortExpression="ShipName" /> |
17 | <asp:BoundField DataField="ShipCity" HeaderText="ShipCity" |
18 | SortExpression="ShipCity" /> |
19 | </Columns> |
20 | </asp:GridView> |
21 | <asp:SqlDataSource ID="sdsOrders" runat="server" |
22 | ConnectionString="<%$ ConnectionStrings:NWind %>" |
23 | SelectCommand="SELECT [OrderID], [CustomerID], [EmployeeID], [OrderDate], [Freight], [ShipName], [ShipCity] FROM [Orders] WHERE ([EmployeeID] = @EmployeeID)"> |
24 | <SelectParameters> |
25 | <asp:Parameter Name="EmployeeID" Type="Int32" /> |
26 | </SelectParameters> |
27 | </asp:SqlDataSource> |
--
wucOdrDetails.ascx
01 | <asp:GridView ID="GridView1" SkinID="GV02" runat="server" |
02 | AutoGenerateColumns="False" DataKeyNames="OrderID,ProductID" |
03 | DataSourceID="sdsOrderDetails"> |
04 | <Columns> |
05 | <asp:BoundField DataField="OrderID" HeaderText="OrderID" ReadOnly="True" |
06 | SortExpression="OrderID" /> |
07 | <asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True" |
08 | SortExpression="ProductID" /> |
09 | <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" |
10 | SortExpression="UnitPrice" /> |
11 | <asp:BoundField DataField="Quantity" HeaderText="Quantity" |
12 | SortExpression="Quantity" /> |
13 | <asp:BoundField DataField="Discount" HeaderText="Discount" |
14 | SortExpression="Discount" /> |
15 | </Columns> |
16 | </asp:GridView> |
17 | <asp:SqlDataSource ID="sdsOrderDetails" runat="server" |
18 | ConnectionString="<%$ ConnectionStrings:NWind %>" |
19 | SelectCommand="SELECT * FROM [Order Details] WHERE ([OrderID] = @OrderID)"> |
20 | <SelectParameters> |
21 | <asp:Parameter Name="OrderID" Type="Int32" /> |
22 | </SelectParameters> |
23 | </asp:SqlDataSource> |
兩種模式會用到的WebUserControl是一樣的,可以複製一份到另一個資料夾,以備等一下使用
接著就要開始來使用,兩種模是從這裡起會有不同的內容,以下分別說明
觀察者模式
首先先幫觀察者模式建立Interface,相關程式碼如下
01 | Imports Microsoft.VisualBasic |
02 |
03 | Public Interface IOrder '訂閱者 |
04 | '定閱後,要處理資料的Sub |
05 | Sub ProcessData(ByVal Data As String) |
06 | End Interface |
07 |
08 | Public Interface IPublisher '發行者 |
09 | '註冊有哪些訂閱者要訂閱我的發行 |
10 | Sub RegOrder(ByVal obj As IOrder) |
11 | End Interface |
接著,一個一個的wuc來處理囉!!
首先是wucGetEmployee.ascx,這個wuc是個發行者。他選了某個Employee後,把EmployeeID發行出去,至於訂閱者收到Employee之後,要做什麼事情,這個跟目前的wucGetEmployee.ascx沒關係,那是別人的事情。
所以我們要在wucGetEmployee.ascx的CodeFile中Implements 這個Interface
1 | Partial Class tOrderMode_wucGetEmployee |
2 | Inherits System.Web.UI.UserControl |
3 | Implements IPublisher |
此時會在畫面中自動多出一段程式碼,這是配合Implements IPublisher的原因
1 | Public Sub RegOrder(ByVal obj As IOrder) Implements IPublisher.RegOrder |
2 | |
3 | End Sub |
接著安排一個本頁的全域變數m_Orders,用這個來記錄有哪些訂閱者,訂閱了這個wuc
1 | Dim m_Orders As New List(Of IOrder) '建立訂閱者的集合變數 |
再來,我們在剛剛的Regorder中,加上要註冊訂閱者的程式碼
1 | Public Sub RegOrder(ByVal obj As IOrder) Implements IPublisher.RegOrder |
2 | m_Orders.Add(obj) '註冊訂閱者 |
3 | End Sub |
另外,這個下拉式選單,結合資料庫後,希望多出一筆請選擇。最後,希望在DropDownList的SelectedIndexChanged時,可以通知每一個訂閱者目前的EmployeeID
01 | Protected Sub ddlEmployee_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlEmployee.DataBound |
02 | Me.ddlEmployee.Items.Insert(0, "--請選擇--") |
03 | End Sub |
04 |
05 | Protected Sub ddlEmployee_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)Handles ddlEmployee.SelectedIndexChanged |
06 | If m_Orders.Count > 0 Then |
07 | For Each odr In m_Orders |
08 | odr.ProcessData(Me.ddlEmployee.SelectedValue) |
09 | Next |
10 | End If |
11 | End Sub |
這樣就完成的這個發行者wucGetEmployee.ascx的部分。
接著,撰寫wucEmpOrder.ascx的部分,對於wucGetEmployee.ascx來說,他是訂閱者(觀察者)所以一開始的時候,先在後端CodeFile加入Implements IOrder,因為Implements了IOrder,畫面會順便帶出ProcessData的部分
1 | Implements IOrder |
2 |
3 | Public Sub ProcessData(ByVal Data As String) Implements IOrder.ProcessData |
4 |
5 | End Sub |
我們希望他訂閱到資料後,將得到的EmployeeID給畫面中的SqlDataSouce於是程式碼
1 | Public Sub ProcessData(ByVal Data As String) Implements IOrder.ProcessData |
2 | '將訂閱到的資料給SqlDataSouce的SelectParameters("EmployeeID") |
3 | Me.sdsOrders.SelectParameters("EmployeeID").DefaultValue = Data |
4 | End Sub |
事實上,wucEmpOrder.ascx他不只是個訂閱者,對OrderDetail來說他也是個發行者,希望選擇GridView裡面的Order之後,就顯是相對應的OrderDetail
過程與上面相似,就不贅述...詳細程式內容請參考本文最後面的範例檔。
最後把這兩個wuc放到畫面後,還需要處理一些些程式。
我們先把這三個wuc拉到畫面中,畫面如下
1 | <uc1:wucGetEmployee ID="wucGetEmployee1" runat="server" /> |
2 | <uc2:wucEmpOrder ID="wucEmpOrder1" runat="server" /> |
3 | <uc3:wucOdrDetails ID="wucOdrDetails1" runat="server" /> |
註冊上去後,他們彼此的關係還沒有設定,因此我們在PageLoad事件中,直行發行者的RegOrder來註冊訂閱者
1 | Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load |
2 | Me.wucGetEmployee1.RegOrder(Me.wucEmpOrder1) |
3 | Me.wucEmpOrder1.RegOrder(Me.wucOdrDetails1) |
4 | End Sub |
這樣在PageLoad的時候,wucGetEmployee1知道了wucEmpOrder1訂閱了他,wucEmpOrder1也知道了wucOdrDetails1訂閱了他。
事件模式
上面說明了觀察者模式後,接著說明事件模式。這兩個模是要做的事情是一樣的,不過裡面運作的概念上卻不太相同。這裡改以觸發事件的方式來處理。
一樣的先撰寫需要的Interface,首先建立一個類別,清除類別的程式碼,改成這樣
01 | Imports Microsoft.VisualBasic |
02 |
03 | '宣告一個事件的Handler |
04 | Public Delegate Sub SetDataHandler(ByVal sender As Object, ByVal Data As String) |
05 |
06 | Public Interface IEventMode |
07 | '設定這個介面有個SetData的事件 |
08 | Event SetData As SetDataHandler |
09 | End Interface |
10 |
11 | Public Interface IReciver |
12 | '設定一個IReciver介面,裡面有UseData的Sub |
13 | Sub UseData(ByVal Data As String) |
14 | End Interface |
設定好後,接著一樣的,先從源頭的wucGetEmployee.ascx開始撰寫起
一樣的,先幫這個wuc的CodeFile安排Implements IEventMode此時會自動產生一個Event的語法
1 | Implements IEventMode |
2 |
3 | Public Event SetData(ByVal sender As Object, ByVal Data As String) Implements IEventMode.SetData |
接著,在DorpDownList的SelectedIndexChanged事件中,要去觸發這個事件,並且將目前的SelectedValue透過事件傳出去
1 | Protected Sub ddlEmployee_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)Handles ddlEmployee.SelectedIndexChanged |
2 | RaiseEvent SetData(Me.ddlEmployee, Me.ddlEmployee.SelectedValue) |
3 | End Sub |
接著安排wucEmpOrder.ascx這個,對於這個而言,當wucGetEmployee.ascx觸發了事件後,他要透過Reciver的UseData把事件中的值給予SqlDataSouce,一樣的要先Implements IReciver介面
1 | Implements IReciver |
2 |
3 | Public Sub UseData(ByVal Data As String) Implements IReciver.UseData |
4 | Me.sdsOrders.SelectParameters("EmployeeID").DefaultValue = Data |
5 | End Sub |
而對於此wuc他不只是Reciver也是EventMode因此也要Implements IEventMode介面,這部分與上面一樣,就不贅述了。
最後要把三個wuc放在畫面上,並且在aspx的CodeFile要處理一下,當三個wuc放到畫面後,畫面並不知道事件觸發應該要影響其他哪些wuc,因此要撰寫SetOrderData與SetOrderDetail這兩個Sub來通知Reciver開始使用事件發生的資料相關的程式碼如下(這部分與C#的程式碼差異度較大,如果是C#的使用者請參考Allen大的範例)
01 | Protected Overrides Sub OnInit(ByVal e As System.EventArgs) |
02 | MyBase.OnInit(e) |
03 | AddHandler Me.wucGetEmployee1.SetData, AddressOf SetOrderData |
04 | AddHandler Me.wucEmpOrder1.SetData1, AddressOf SetOrderDetailData |
05 |
06 | End Sub |
07 |
08 | Public Sub SetOrderData(ByVal sender As Object, ByVal Data As String) |
09 | '設定 |
10 | Me.wucEmpOrder1.UseData(Data) |
11 | Me.wucOdrDetails1.UseData("") |
12 |
13 | End Sub |
14 | Public Sub SetOrderDetailData(ByVal sender As Object, ByVal Data As String) |
15 | Me.wucOdrDetails1.UseData(Data) |
16 | End Sub |
最後小喵將相關程式碼壓縮在此
請下載參考
http://vip2.blueshop.com.tw/topcat/DEMO/UC2UC/UC2UC.zip
- 6月 20 週三 201212:09
[ASP.NET]從usercontrol傳值給page
您可以在UserControl中宣告事件:
Public Event DataChanged(ByVal s As String) '宣告事件
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
RaiseEvent DataChanged("Hello") '在按鍵被點下時引發事件並傳出資料
End Sub
Public Event DataChanged(ByVal s As String) '宣告事件
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
RaiseEvent DataChanged("Hello") '在按鍵被點下時引發事件並傳出資料
End Sub
- 3月 13 週二 201208:51
AD環境下大量佈署XP的SNMP
轉載自:http://blog.swto.net/2010/01/adxpsnmp.html
安裝完一堆XP後發現有需要裝內建的SNMP服務!一台一台裝?太累了,用群組原則執行這個批次檔就ok了!這可是我翻遍了好幾個國外論壇,用多個技巧組合而來的!
安裝完一堆XP後發現有需要裝內建的SNMP服務!一台一台裝?太累了,用群組原則執行這個批次檔就ok了!這可是我翻遍了好幾個國外論壇,用多個技巧組合而來的!