User conrols là các controls do người dùng định nghĩa, có thể được sử dụng lại bởi các trang trong site. Một user control có thể giống một trang ASPX vì nó bao gồm:

  • Các mã HTML, các server controls,…
  • Nó có thể được thiết kế trong VS ở 3 chế độ Design, SourceSplit.
  • Nó có thể được lập trình.
  • Có thể truy cập bằng phương thức QueryString.
  • Nó có thể phát sinh các sự kiện như Init, LoadPreRender.

Tuy nhiên, user control có một vài điểm khác biệt với một trang ASPX là:

  • Nó có phần mở rộng là .ASCX
  • Không thể được yêu cầu một cách trực tiếp từ trình duyệt web, do đó, không thể liên kết đến nó trực tiếp.
  • Dùng user control bằng cách thêm nó đến một trang hay một control nào đó.

Tạo user controls

Tạo một user control giống tạo một trang ASPX, cũng chọn Add > Add New Item, nhưng thay vì chọn Web Form chúng ta chọn Web User Control. Để hiểu hơn về cách tạo một user control chúng ta sẽ đến phần thực hành tạo user control dưới đây.

Thực hành tạo một user control

Trong bài thực hành này chúng ta sẽ tạo ra một user control hiển thị một banner dọc (vertical) bằng cách dùng Image control. Để hoàn thành bài thực hành, chúng ta cần 2 ảnh kích thước lần lượt là 120 X 240 (pixel) và 486 X 60 (pixel), giả sử các ảnh là Anh_120_140.gifAnh_486_60.gif (trong thư mục tài nguyên).

  • Tạo một thư mục tên Images (Nhấp chuột phải vào Site, chọn Add > New Folder). Copy hai ảnh gif vào thư mục Images.
  • Thêm một user control vào thư mục Controls (đã tạo từ các chương trước, nếu chưa thì tạo ra) bằng cách nhấp chuột phải Controls chọn Add > Add New Item và chọn Web User Control, đặt tên file là Banner với phần mở rộng mặc định là ascx và chú ý các tuỳ chọn:

  • Mở file Banner.ascx trong thư mục Controls ở chế độ Design. Kéo một Panel từ mục Standard của Toolbox thả vào bề mặt thiết kế, thay đổi thuộc tính ID của Panel thành VerticalPanel:

  • Từ Toolbox, mục Standard, kéo Image control thả vào Panel. Trong hộp thoại Properties của Image, chọn thuộc tính ImageUrl và nhấp vào button bên phải để tìm đến thư mục Images và chọn file gif từ hộp thoại Select Image để thêm nó vào user control và bấm OK, kết quả:

  • Cũng trong hộp thoại Properties của Image, tìm đến thuộc tính AlternateText và gõ dòng text Đây là một banner. Dòng text này sẽ được trình duyệt web hiển thị trong trường hợp không tìm thấy file ảnh.
  • Bây giờ, giả sử chúng ta muốn khi nhấp chuột vào banner thì sẽ liên kết đến một trang web nào đó, ví dụ http:// http://www.microsoft.com, thì làm như sau: mở trang Banner.ascx sang chế độ Resource: 

Thêm một liên kết (thẻ a) cho banner như đoạn mã sau:

  • Lưu và đóng file Banner.ascx.

Thêm user control đến trang (nội dung hay master) hoặc control khác

Để thêm user control chúng ta thực hiện hai bước. Bước 1, chúng ta phải đăng kí user control bằng cách thêm chỉ định @ Register đến trang hay control khác. Bước 2 thêm vài thẻ và thiết lập một vài thuộc tính. Một chỉ định @ Register cho một user control trông giống như sau:


<%@ Register Src="ControlName.ascx" TagName="ControlName" TagPrefix="uc1" %>

Ba thuộc tính quan trọng của @ Register:

Thuộc tính Mô tả
Src Trỏ đến user control bạn cần dùng.
TagName Tên thẻ dùng khai báo user control trong trang hay control khác.
TagPrefix Tiền tố (prefix) của TagName trong khai báo control.

 

Ví dụ đăng kí user control với @ Register như sau:


<%@ Register Src = "~/Controls/Banner.ascx" TagName = "Banner" TagPrefix = "uc1" %>

Với đăng kí như trên, khi thêm user control này vào trang chúng ta dùng như sau:


<uc1:Banner ID="Banner1" runat="server" />

Chúng ta thấy rằng, khi dùng user control thì cặp TagPrefixTagName đi liền nhau; thuộc tính IDrunat là hai thuộc tính cơ bản giống nhu mọi server controls khác.

Tuy nhiên, khi chúng ta thêm user control vào trang, chúng ta không cần gõ những đoạn code trên, mọi thứ đều được VS tự động phát sinh khi chúng ta kéo một user control vào vùng thiết kế. Để rõ hơn chúng ta sẽ thực hiện bài thực hành thêm user control sau.

Thực hành thêm user control đến trang

  • Mở trang master Frontend.master ở chế độ Design. Đưa con trỏ chuột vào bên phải DropDownList chứa các themes, gõ 3 lần phím Enter để tạo một khoảng trống

  • Từ cửa sổ Solution Explorer, kéo Banner.ascx từ thư mục Controls và thả vào vùng trống vừa tạo (tại vị trí cách DropDownList 3 lần Enter):

Mở trang master sang chế độ Resource sẽ thấy chỉ định @ Register ở đầu trang

  • Nếu để ý chúng ta thấy xung quanh ảnh của banner có viền xanh, có thể để viền như trên hoặc bỏ nó đi bằng cách vào file Monochrome.css (và DarkGrey.css) và thêm đoạn CSS sau:
     img { border: 0; } 
  • Lưu, chọn trang Content.aspxCtrl + F5

  • Nhấn chuột vào banner sẽ chuyển đến trang microsoft.com.

Thêm user control đến toàn bộ site

Chúng ta có thể làm cho user control, ví dụ như Banner.ascx, có thể được sử dụng trong toàn bộ site thay vì phải đăng kí (dùng chỉ định @ Register ) cho một trang nào đó. Để làm điều này, chúng ta sẽ đăng kí dùng user control trong Web.config.

Thực hành áp dụng user control đến toàn bộ site

  • Mở trang master Frontend.master ở chế độ Resource và xoá chỉ định @ Register ở đầu trang. Mở file Web.config, tìm đến phần tử <pages /> như sau:

và thêm phần tử <controls> cùng  với phần tử con của nó là <add> vào <pages>:

  1. Lưu và đóng file Web.config. Mở lại trang Frontend.master ở chế độ Resource, tìm đến Banner control và thay đổi TagPrefix từ uc1 thành ngocminhtran

  1. Lưu và đóng Frontend.master. Chọn trang Content.aspxCtrl + F5. Kết quả giống như việc chúng ta đăng kí Banner trong trang master ở bài thực hành trên.

Chú ý khi dùng user control

Trong bài thực hành trên, khi Panel chứa Banner hiển thị trên trình duyệt web, nó sẽ được gán đến idBanner1_VerticalPanel (chọn View page source):

id này sẽ rất quan trọng nếu chúng ta cần truy cập control này từ client thộng qua JavaScript hay CSS. Nhưng làm sao để biết giá trị id của user control khi ở server? ASP.NET cung cấp một thuộc tính gọi là ClientID để lấy id của user control. Ví dụ chúng ta đã gán ID cho Panel khi tạo user contol Banner.ascxVerticalPanel, xét đoạn mã sau:

Label1.Text = VerticalPanel.ClientID

Đoạn mã trên sẽ gán id của user control ở trình duyệt (hay client) vào thuộc tính Text của Label1, kết quả trên Label1 sẽ hiển thị Banner1_VerticalPanel (như ở trên khi vào View page source). Như vậy, khi ở phía server, nếu chúng ta muốn dùng id phía client của user control, chúng ta dùng ClientID.

Kể từ phiên bản ASP.NET 4, các web control có thêm thuộc tính là ClientIDMode tác động đến id phía client của control. ClientIDMode có 4 giá trị:

Thuộc tính Mô tả
AutoID Phát sinh id như các phiên bản ASP.NET trước đó.
Inherit Giá trị thừa kế từ các control cha.
Predictable Dùng trong các control ràng buộc dữ liệu và cho phép tạo ra các ClientID có thể dự đoán trước khi lập lại các controls.
Static Nếu giá trị này được thiết lập thì id ở client và id ở server giống nhau.

 

Lập trình cho user control

Banner control chúng ta đã tạo chỉ có khả năng hiển thị trang microsoft.com khi chúng ta nhấp chuột vào nó. Chúng ta có thể làm cho control này “thông minh hơn” bằng cách thêm các thuộc tính, phương thức cho nó.

Giả sử chúng ta muốn Banner có thể hiển thị theo chiều ngang và dọc, để làm được điều đó, chúng ta sẽ tạo ra một kiểu dữ liệu mới, dành riêng cho Banner, dùng dạng kiệt kê (enumeration) hay enum. Định nghĩa kiểu dữ liệu mới tên Direction gồm hai thành phần con là VerticalHorizontal dạng Enum:


Public Enum Direction

Horizontal

Vertical

End Enum

Trình biên dịch sẽ tự động gán giá trị (bắt đầu là 0) cho HorizontalVertical, hoặc chúng ta có thể gán giá trị như sau:


Public Enum Direction

Horizontal = 0

Vertical = 1

End Enum

Khai báo, sử dụng kiểu dữ liệu và lập trình cho Banner sẽ được minh hoạ qua bài thực hành dưới đây.

Thực hành lập trình cho user control

  • Chọn và nhấp chuột phải vào thư mục App_Code, chọn Add > Add New Item, chọn Class, tên file là Direction

  • Xoá tất cả code trong file Direction, thêm đoạn code sau:

  • Lưu và đóng file.
  • Mở file VB của Banner.ascx (Banner.ascx.vb), thêm một Property cho user control bằng cách gõ đoạn mã sau:

  • Ở trên chúng ta đã thêm một Property tên là DisplayDirection có kiểu dữ liệu là Direction mà chúng ta đã định nghĩa ở trên.
  • Mở file Banner.ascx ở chế độ Sourcecopy toàn bộ đoạn <asp: Panel> Paste vào ngay dưới, thiết lập lại ID của PanelImageUrl của Image như sau:

  • Trở lại file Banner.ascx.vb, chọn Page Events từ cửa sổ bên trái và Load cửa sổ bên phải để đến sự kiện Load:

Thêm đoạn mã sau:

Lưu và đóng file.

  • Mở trang master Frontend.master ở chế độ Source, chọn <ngocminhtran:Banner> và sau thuộc tính runat thêm thuộc tính DisplayDirection (đã tạo ở trên) với giá trị là Horizontal:

  • Lưu tất cả, chọn trang Content.aspxCtrl + F5.

Chúng ta thấy banner vượt quá chiều rộng sidebar. Trở lại trang master, thay đổi giá trị thuộc tính DisplayDirection từ Horizontal đến Vertical. Lưu, chọn lại Content.aspxCtrl + F5:

  • Chọn trang AboutUs.aspx (trong thư mục About) ở chế độ Source, trong cpMainContent gõ một vài dòng text mô tả website, mục đích, giới thiệu bản thân, v.v. Chuyển trang sang chế độ Design, kéo Banner.ascx từ cửa sổ Solution Explorer thả vào dưới các dòng text vừa gõ, VS sẽ tự động gán IDBanner2 (vì Banner1 đã tồn tại trong trang master). Chọn banner này, nhấp chuột phải chọn Properties và thiết lập giá trị cho thuộc tính DisplayDirectionHorizontal.

  • Lưu tất cả và Ctrl + F5 để thực thi trang AboutUs.aspx, kết quả sẽ xuất hiện hai banner, một trong sidebar và một trong vùng nội dung:

Các thuộc tính View State

Thuộc tính View State có nhiều tác dụng và để thực thi một thuộc tính nào đó theo kiểu View State, chúng ta dùng collection ViewState. Để hiểu hơn cách dùng thuộc tính View State, chúng ta sẽ thực hiện phần thực hành dưới đây.

Thực hành với thuộc tính View State

  • Nhấp vào vị trí bất kì trong vùng xám của trang AboutUs.aspx ở chế độ Design để đến trình xử lí sự kiện Page_Load và gõ đoạn mã sau (bôi đen):

  • Trở lại trang AboutUs.aspx ở chế độ Design, kéo một button từ ToolBox và thả vào vị trí giữa dòng text và Banner trong vùng nội dung của trang

  • Lưu và Ctrl + F5, chúng ta thấy rằng ban đầu banner sẽ hiển thị theo chiều dọc, nếu chúng ta nhấn button trang tải lại và banner sẽ chuyển qua chiều ngang bởi vì, như trong đoạn mã VB trong Page_Load ở trên, thuộc tính DisplayDirection chỉ được thiết lập khi giá trị của Page.IsPostBackFasle, nghĩa là các thiết lập mặc định của banner sẽ thay đổi (từ Horiziontal thành Vertical).
  • Để tránh phiền phức trên, chúng ta sẽ định nghĩa thuộc tính View State tên là NavigateUrl dùng collection ViewState. Trong file Banner.ascx.vb, dưới dòng khai báo thuộc tính DisplayDirection, gõ đoạn mã khai báo thuộc tính NavigateUrl theo kiểu View State như sau:

  • Chuyển đến file Banner.ascx ở chế độ Source, thêm thuộc tính runat và các id cho các liên kết (thẻ a) như sau:

  • Trở lại file Banner.ascx.vb, bổ sung các dòng code sau vào Page_Load:

  • Lưu thay đổi vừa thực hiện. Mở file AboutUs.aspx.vb, trong Page_Load thay thuộc tính DisplayDirection bằng NavigateUrl như sau:

  • Lưu, chọn lại AboutUs.aspx Ctrl + F5. Kết quả là banner ngang và khi nhấp chuột vào banner sẽ mở một cửa sổ mới đến trang codeproject.com (nếu có kết nối Internet). Nhấp vào button để tạo một post back, trang tải lại thì kết quả vẫn không thay đổi.
  • Mở lại trang AboutUs.aspx.vb, gán giá trị NavigateUrlNothing:

  • Thực thi lại trang AboutUs.aspx và kết quả???  (Để hiểu chúng ta xem lại đoạn mã trong khai báo thuộc tính NavigateUrl ở trên).

Chú ý khi dùng View State

Qua phần thực hành trên, chúng thấy thuộc tính View State (cụ thể là NavigateUrl) giúp chúng ta biến user control (Banner) thành URL, đồng thời giúp duy trì trạng thái trang sau khi post back. Điều này có được nhờ khả năng lưu trữ dữ liệu trong View State (hơi giống cookie). Tuy nhiên, nếu chúng ta lưu trữ dữ liệu lớn trong View State sẽ ảnh hưởng xấu đến khả năng thực thi của trang (chậm); đồng thời, giống cookie, không nên lưu trữ các dữ liệu nhạy cảm trong View State.