You are on page 1of 102

Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

MỤC LỤC
CHƯƠNG 1: TỔNG QUAN VỀ C# .......................................................................................................... 1
1.1. Giới thiệu Microsoft Visual Studio 2013.................................................................................1
1.1.1. Visual Studio Color Themes .............................................................................................1
1.1.2. Giao diện làm việc chính của Visual Studio...................................................................2
1.1.3. Các cửa sổ bị ẩn trên giao diện Visual Studio ................................................................4
1.1.4. Build, Debug và Run ..........................................................................................................5
1.1.5. Xác định Project khởi động chương trình .......................................................................5
1.2. Giới thiệu C# .................................................................................................................................7
1.2.1. C# là ngôn ngữ đơn giản ....................................................................................................8
1.2.2. C# là ngôn ngữ hiện đại......................................................................................................8
1.2.3. C# là ngôn ngữ hướng đối tượng......................................................................................8
1.2.4. C# là ngôn ngữ mạnh mẽ và mềm dẻo ...........................................................................8
1.2.5. C# là ngôn ngữ hướng module .........................................................................................8
1.2.6. C# sẽ trở nên phổ biến ........................................................................................................9
1.3. Môi trường lập trình.....................................................................................................................9
1.3.1. Sử dụng Notepad soạn thảo...............................................................................................9
1.3.2. Sử dụng Micosoft Visual Studio để tạo chương trình...................................................9
1.4. Quy tắc lập trình, ứng dụng Console Application ............................................................... 10
1.4.1. Quy tắc lập trình................................................................................................................ 10
1.4.2. Ứng dụng Console Application ..................................................................................... 11
1.5. Biến .............................................................................................................................................. 12
1.5.1. Khái niệm........................................................................................................................... 12
1.5.2. Khai báo biến..................................................................................................................... 12
1.5.3. Ví dụ.................................................................................................................................... 12
1.6. Hằng............................................................................................................................................. 13
1.6.1. Khái niệm........................................................................................................................... 13
1.6.2. Giá trị hằng: ....................................................................................................................... 13
1.6.3. Biểu tượng hằng................................................................................................................ 13
1.6.4. Kiểu liệt kê ......................................................................................................................... 14
1.7. Toán tử ........................................................................................................................................ 15
1.8. Kiểu dữ liệu ................................................................................................................................ 15
Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

1.8.1. Kiểu dữ liệu dựng sẵn .......................................................................................................15


1.8.2. Chuyển đổi kiểu dữ liệu ...................................................................................................16
CHƯƠNG 2: CẤU TRÚC ĐIỀU KHIỂN............................................................................................. 17
2.1. Giới thiệu .....................................................................................................................................17
2.2. Câu lệnh if … else ....................................................................................................................18
2.3. Câu lệnh if lồng nhau................................................................................................................18
2.4. Câu lệnh switch ..........................................................................................................................19
2.5. Cấu trúc lặp..................................................................................................................................20
2.5.1. While....................................................................................................................................20
2.5.2. Do … while ........................................................................................................................21
2.5.3. For.........................................................................................................................................22
2.5.4. Foreach ................................................................................................................................22
CHƯƠNG 3: DỮ LIỆU KIỂU MẢNG .................................................................................................. 28
3.1. Mảng 1 chiều...............................................................................................................................28
3.1.1. Định nghĩa...........................................................................................................................28
3.1.2. Khai báo mảng:..................................................................................................................28
3.1.3. Khởi tạo thành phần của mảng .......................................................................................28
3.1.4. Giá trị mặc định: ................................................................................................................28
3.1.5. Truy cập các thành phần trong mảng:............................................................................29
3.1.6. Duyệt mảng 1 chiều: .........................................................................................................29
3.2. Mảng nhiều chiều.......................................................................................................................33
3.2.1. Định nghĩa...........................................................................................................................33
3.2.2. Khai báo mảng 2 chiều.....................................................................................................33
3.2.3. Khởi tạo thành phần của mảng .......................................................................................33
3.2.4. Duyệt mảng 2 chiều ..........................................................................................................33
3.3. Exception (Ngoại lệ)..................................................................................................................35
3.3.1. Khái niệm............................................................................................................................36
3.3.2. Ví dụ.....................................................................................................................................36
CHƯƠNG 4: CLASS - OBJECT – METHOD ................................................................................... 41
4.1. Khái niệm ....................................................................................................................................41
4.2. Định nghĩa lớp (class)................................................................................................................41
4.2.1. Cú pháp ...............................................................................................................................41
4.2.2. Ví dụ.....................................................................................................................................41
4.3. Properties - Method....................................................................................................................46
Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

4.3.1. Thuộc tính (Properties) .................................................................................................... 46


4.3.2. Thuộc tính truy cập........................................................................................................... 46
4.3.3. Phương thức (Method) .................................................................................................... 47
4.3.4. Tham số của phương thức .............................................................................................. 47
4.3.5. Ví dụ.................................................................................................................................... 48
CHƯƠNG 5: LẬP TRÌNH ĐIỀU KHIỂN FORM ............................................................................ 52
5.1. Giới thiệu..................................................................................................................................... 52
5.1.1. Thuộc tính, sự kiện và phương thức của biểu mẫu .................................................... 52
5.1.2. Thao tác với form trong một ứng dụng ........................................................................ 54
5.1.3. Viết code cho các sự kiện trên form .............................................................................. 54
5.1.4. Form MDI.......................................................................................................................... 56
5.2. Các hộp thoại thông báo........................................................................................................... 56
5.2.1. MessageBox ...................................................................................................................... 56
5.2.2. OpenFileDialog................................................................................................................. 57
5.2.3. SaveFileDialog.................................................................................................................. 58
5.2.4. FontDialog ......................................................................................................................... 59
5.2.5. ColorDialog ....................................................................................................................... 60
5.2.6. PrintDialog ......................................................................................................................... 60
5.3. Menu............................................................................................................................................ 60
5.3.1. MenuStrip .......................................................................................................................... 60
5.3.2. ContextMenuStrip ............................................................................................................ 61
CHƯƠNG 6: KIẾN TRÚC ADO.NET................................................................................................... 65
6.1. Active Data Object - ADO.NET............................................................................................ 65
6.1.1. Mô hình Kết nối................................................................................................................ 65
6.1.2. Mô hình Ngắt Kết nối ...................................................................................................... 66
6.1.3. Làm việc với mô hình Kết nối trong ADO.NET ....................................................... 68
6.2. Các thành phần cốt lõi trong ADO.NET .............................................................................. 68
6.3. Đối tượng Connection .............................................................................................................. 70
6.3.1. Connection string.............................................................................................................. 71
6.3.2. Connection Pooling.......................................................................................................... 72
6.4. Đối tượng Command ............................................................................................................... 73
6.4.1. Tạo đối tượng Command................................................................................................ 73
6.4.2. Thực thi một Command.................................................................................................. 74
6.4.3. Thực thi Stored Procedure (thủ tục lưu trữ sẵn) với đối tượng Command ........... 76
Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

6.4.4. Sử dụng Parameter trong các Command không phải là Stored Procedures...........78
6.5. Đối tượng DataReader ..............................................................................................................78
6.5.1. Truy xuất các dòng dữ liệu với DataReader .................................................................79
6.5.2. Truy xuất giá trị của column............................................................................................79
6.6. Làm việc với mô hình Ngắt kết nối: DataSet và DataTable ..............................................81
6.6.1. Lớp DataSet........................................................................................................................81
6.6.2. Nạp dữ liệu vào DataSet...................................................................................................86
6.6.3. Cập nhật CSDL bằng DataAdapter ...............................................................................88
6.7. Lựa chọn giữa mô hình Kết nối và mô hình Ngắt kết nối ..................................................90
CHƯƠNG 7: BÁO CÁO.............................................................................................................................. 93
7.1. Crystal Report .............................................................................................................................93
7.2. Hướng dẫn sử dụng report wizart............................................................................................93
Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

CHƯƠNG 1: TỔNG QUAN VỀ C#


1.1. Giới thiệu Microsoft Visual Studio 2013
Microsoft Viual Studio (VS) là một IDE được Microsoft phát triển để hỗ trợ các
lập trình viên trong quá trình viết mã. Ngoài chức năng cơ bản là viết mã, build và
debug, VS còn cung cấp cho người dùng những chức năng như:
- Làm việc nhóm thông qua Team Foundation Server của Microsoft.
- Advanced Breakpoints.
- Các phím tắt và plugins hỗ trợ người dùng thao tác nhanh trong việc viết mã.
- Wizard Classes.
- Tùy chỉnh liên kết các project và thư viện, tập tin liên quan.

1.1.1. Visual Studio Color Themes


VS 2013 có 3 bộ theme chính phục vụ người dùng là Dark, Blue và Light. Điểm
khác biệt của 3 bộ theme này chỉ là màu sắc của giao diện làm việc, các hình ảnh sử
dụng trong bài viết thuộc về bộ theme Dark.
Để thay đổi màu sắc, người dùng chỉ cần vào Tools -> Option

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 1


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Tại cửa sổ vừa hiện lên, tại mục General chọn Color theme cần đổi và bấm OK.

1.1.2. Giao diện làm việc chính của Visual Studio

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 2


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Để bắt đầu làm việc với VS, người dùng cần phải tạo hoặc mở ra
một Solution và tạo hoặc mở một hoặc nhiều Project trong đó.
Ví dụ một Solution, và giao diện VS như sau:

Solution Explorer: là cửa sổ hiển thị Solution, các Project và các tập tin trong
project.
Khu vực code: đây là khu vực để lập trình viên viết mã nguồn cho chương
trình. Cửa sổ lập trình cho một tập tin trong Project sẽ hiển thị khi người dùng nháy
đúp chuột lên tập tin đó trong cửa sổ Solution Explorer.
Output: đây là cửa sổ hiển thị các thông tin, trạng thái của Solution khi build
hoặc của chương trình khi debug.
Error List: là cửa sổ hiển thị danh sách lỗi (Error) hoặc cảnh báo (Warning) của
chương trình khi build.
Toolbar với các công cụ hỗ trợ người dùng trong việc viết mã và debug (các
công cụ trên thanh có thể thay đổi khi bắt đầu debug).

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 3


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Thanh menu với đầy đủ các danh mục chứa các chức năng của VS. Khi người
dùng cài thêm những trình cắm hỗ trợ VS (ví dụ như Visual Assist), thanh menu này
sẽ cập nhật thêm menu của các trình cắm (nếu có).
Một lưu ý thêm là các cửa sổ trong giao diện làm việc của VS không được gắn
cố định, nên người dùng có thể tự do tùy chỉnh khung làm việc của mình sao cho phù
hợp nhất. Độc giả có thể thử click vào thanh tiêu đề của một cửa sổ hoặc một thẻ tập
tin code và kéo ra khỏi vị trí của nó, một số biểu tượng hỗ trợ sẽ xuất hiện trên giao
diện VS để người dùng “thả” cửa sổ vừa kéo ra vào đó hoặc thả trôi nổi như một
popup trên giao diện VS.
1.1.3. Các cửa sổ bị ẩn trên giao diện Visual Studio
Đôi khi giao diện của VS trở nên quá dày đặc do quá nhiều cửa sổ, lúc này giải
pháp được VS đưa ra là “gộp” nhiều cửa sổ lại với nhau và quản lý dưới dạng “thẻ”.
Nội dung của cửa sổ sẽ được hiển thị khi ta click vào thẻ tương ứng.
Ví dụ về một số vị trí đặt thẻ trên giao diện VS:

Thêm cửa sổ vào giao diện Visual Studio:


Đôi khi một số cửa sổ không được kích hoạt sẵn trên giao diện cơ bản của VS,
hoặc cũng có thể do người dùng vô tình tắt mất. Để hiển thị cửa sổ mong muốn, người
dùng có thể vào View và chọn cửa sổ cần hiển thị.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 4


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Một số cửa sổ được đặt trong View -> Other Windows, các thanh công cụ
được đặt trong View -> Toolbars.

1.1.4. Build, Debug và Run


Ở các phiên bản từ VS 2012 trở về trước, phím tắt mặc định để Build một
Solution là F7, tuy nhiên ở phiên bản VS 2013, thao tác này được chuyển đến tổ hợp
phím Ctrl + Shift + B.
Để bắt đầu Debug một Solution, ta sử dụng phím tắt F5.
Để Run một Solution, ta sử dụng tổ hợp phím Ctrl + F5.
1.1.5. Xác định Project khởi động chương trình
Đối với những Solution có nhiều Project, vấn đề xảy ra khi ta sử dụng phím tắt
để chạy chương trình. Giả sử mỗi Project là một chương trình riêng biệt, có
hàm main riêng, làm sao để VS biết ta cần chạy hay debug project nào?

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 5


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Nếu có nhiều Project, ta có thể thấy rằng: trong các project đó có một project
được đặt tên in đậm – đó là Startup Project, khi ta khởi chạy hoặc debug từ phím tắt
thì hàm main trong project này sẽ được gọi.

Để thiết lập Startup Project ta cần click phải chuột lên project muốn đặt làm
startup và chọn Set as Startup Project.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 6


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

1.2. Giới thiệu C#


Ngôn ngữ C# khá đơn giản, chỉ khoảng hơn 80 từ khóa và hơn mười mấy kiểu
dữ liệu được dựng sẵn. Tuy nhiên, ngôn ngữ C# có ý nghĩa to lớn khi nó thực thi
những khái niệm lập trình hiện đại. C# bao gồm tất cả những hỗ trợ cho cấu trúc,
thành phần component, lập trình hướng đối tượng. Những tính chất đó hiện diện trong
một ngôn ngữ lập trình hiện đại.
Hơn nữa ngôn ngữ C# được xây dựng trên nền tảng hai ngôn ngữ mạnh nhất là
C++ và Java.
Tóm lại, C# có các đặc trưng sau đây:
- C# là ngôn ngữ đơn giản
- C# là ngôn ngữ hiện đại
- C# là ngôn ngữ hướng đối tượng

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 7


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

- C# là ngôn ngữ mạnh mẽ và mềm dẻo


- C# là ngôn ngữ hướng module
- C# sẽ trở nên phổ biến
1.2.1. C# là ngôn ngữ đơn giản
- C# loại bỏ được một vài sự phức tạp và rối rắm của các ngôn ngữ C++ và Java.
- C# khá giống C / C++ về diện mạo, cú pháp, biểu thức, toán tử.
- Các chức năng của C# được lấy trực tiếp từ ngôn ngữ C / C++ nhưng được cải
tiến để làm cho ngôn ngữ đơn giản hơn.
1.2.2. C# là ngôn ngữ hiện đại
C# có được những đặc tính của ngôn ngữ hiện đại như:
- Xử lý ngoại lệ
- Thu gom bộ nhớ tự động
- Có những kiểu dữ liệu mở rộng
- Bảo mật mã nguồn
1.2.3. C# là ngôn ngữ hướng đối tượng
C# hỗ trợ tất cả những đặc tính của ngôn ngữ hướng đối tượng là:
- Sự đóng gói (encapsulation)
- Sự kế thừa (inheritance)
- Đa hình (polymorphism)
1.2.4. C# là ngôn ngữ mạnh mẽ và mềm dẻo
- Với ngôn ngữ C#, chúng ta chỉ bị giới hạn ở chính bản thân của chúng ta. Ngôn
ngữ này không đặt ra những ràng buộc lên những việc có thể làm.
- C# được sử dụng cho nhiều dự án khác nhau như: tạo ra ứng dụng xử lý văn
bản, ứng dụng đồ họa, xử lý bảng tính; thậm chí tạo ra những trình biên dịch cho các
ngôn ngữ khác.
- C# là ngôn ngữ sử dụng giới hạn những từ khóa. Phần lớn các từ khóa dùng
để mô tả thông tin, nhưng không vì thế mà C# kém phần mạnh mẽ. Chúng ta có thể
tìm thấy rằng ngôn ngữ này có thể được sử dụng để làm bất cứ nhiệm vụ nào.
1.2.5. C# là ngôn ngữ hướng module
- Mã nguồn của C# được viết trong Class (lớp). Những Class này chứa
các Method (phương thức) thành viên của nó.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 8


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

- Class (lớp) và các Method (phương thức) thành viên của nó có thể được sử
dụng lại trong những ứng dụng hay chương trình khác.
1.2.6. C# sẽ trở nên phổ biến
C# mang đến sức mạnh của C++ cùng với sự dễ dàng của ngôn ngữ Visual
Basic.
1.3. Môi trường lập trình
1.3.1. Sử dụng Notepad soạn thảo
- Bước 1: Soạn thảo tập tin và lưu với tên C:\ChaoMung.cs có nội dung như sau
class ChaoMung

{
static void Main()
{
// Xuat ra man hinh chuoi thong bao 'Chao mung ban den voi C#
2013'
System.Console.WriteLine("Chao mung ban den voi C# 2013 ") ;
System.Console.ReadLine() ;
}
}

- Bước 2: Vào menu Start  All Programs  Microsoft Visual Studio 2013 
Visual Studio Tools  Visual Studio 2013 Command Prompt
- Bước 3: Gõ lệnh biên dịch tập tin ChaoMung.cs sang tập tin ChaoMung.exe
C:\> csc /t:exe /out:chaomung.exe chaomung.cs
Chạy tập tin ChaoMung.exe và được kết quả như sau :
C:\> chaomung.exe
Chao mung ban den voi C# 2013
1.3.2. Sử dụng Micosoft Visual Studio để tạo chương trình
- Bước 1: Khởi động Visual Studio 2013

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 9


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Start  All Programs  Microsoft Visual Studio


- Bước 2: Vào menu File  New  Project
- Bước 3: Khai báo

* Mặc định: Visual Studio 2013 (Visual Studio .NET) sẽ tạo ra tập tin Program.cs
chứa một namespace tên ChaoMung và trong namespace này chứa một class tên Program.
- Bước 4: trong phương thức Main, gõ đoạn mã lệnh sau
* Ví dụ:
// Xuat ra man hinh chuoi thong bao 'Chao mung ban den voi C# 2013 '
System.Console.WriteLine("Chao mung ban den voi C# 2013 ") ;
System.Console.ReadLine() ;
- Bước 5: Để chạy chương trình, nhấn F5 hoặc nhắp vào nút
1.4. Quy tắc lập trình, ứng dụng Console Application
1.4.1. Quy tắc lập trình
Khi tạo một chương trình trong C#, chúng ta nên thực hiện theo các bước sau:
- Bước 1: Xác định mục tiêu của chương trình
- Bước 2: Xác định những phương pháp giải quyết vấn đề
- Bước 3: Tạo một chương trình để giải quyết vấn đề
- Bước 4: Thực thi chương trình để xem kết quả

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 10


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

1.4.2. Ứng dụng Console Application


Là ứng dụng giao tiếp với người dùng thông qua bàn phím và không có giao
diện người dùng (UI).
Ví dụ 1.3:
using System;
class ChaoMung
{
static void Main()
{
// Xuat ra man hinh chuoi thong bao 'Chao mung ban den voi C# 2013 '
Console.WriteLine("Chao mung ban den voi C# 2013 ") ;
Console.ReadLine() ;
}
}
* Phần Bổ sung
- Namespace:
+ .NET cung cấp một thư viện các class rất đồ sộ, trong đó Console là một
class nhỏ trong thư viện các class này.
+ Mỗi class có một tên riêng, vì vậy người lập trình không thể nào nhớ hết
tên các class trong .NET. Để giải quyết vấn đề này là việc tạo ra một namespace,
namespace sẽ hạn chế phạm vi của một tên, làm cho tên này chỉ có ý nghĩa trong vùng
đã định nghĩa.
- Từ khóa using
+ Để không phải viết namespace cho từng đối tượng, ta dùng từ khóa using.
+ Ta có thể dùng dòng lệnh sau ở đầu chương trình:
using System ;
Khi đó, thay vì viết đầy đủ System.Console. ta chỉ cần viết Console.
- Từ khóa static
Từ khóa static chỉ ra rằng hàm Main() có thể được gọi mà không cần phải
tạo đối tượng ChaoMung.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 11


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

- Từ khóa this
Từ khóa this dùng để tham chiếu đến thể hiện hiện hành của đối tượng.
- Chú thích (Comment)
+ Một chương trình được viết tốt thì cần phải có chú thích các đoạn mã lệnh
được viết. Mục đích chính là làm cho đoạn mã lệnh nguồn rõ ràng và dễ hiểu.
+ Có 2 loại chú thích:
. Chú thích một dòng: //
. Chú thích nhiều dòng: /* */
- Phân biệt chữ thường và chữ hoa
C# là ngôn ngữ phân biệt chữ thường với chữ hoa.
- Toán tử '. '
Toán tử '. ' được sử dụng để truy cập đến phương thức hay dữ liệu trong một
class và ngăn cách giữa tên class đến một namespace.
Ví dụ: System.Console.WriteLine()
Tương ứng: namespace, class and method
- Câu lệnh (statement)
Một chỉ dẫn lập trình đầy đủ được gọi là một câu lệnh.
Ví dụ: int bankinh = 5 ; // một câu lệnh
chuvi = 2 * bankinh * PI ; // một câu lệnh khác
1.5. Biến
1.5.1. Khái niệm
- Biến là một vùng lưu trữ ứng với một kiểu dữ liệu.
- Biến có thể được gán giá trị và cũng có thể thay đổi giá trị trong khi thực hiện
các lệnh của chương trình.
1.5.2. Khai báo biến
Sau khi khai báo biến phải gán giá trị cho biến
<Kiểu_Dữ_Liệu> <tên_biến> [ = <giá_trị> ] ;
1.5.3. Ví dụ
Ví dụ 1.1: Khởi tạo và gán giá trị một biến
class Bien
{

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 12


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

static void Main()


{
// Khai bao va khoi tao bien
int bien = 9 ;
System.Console.WriteLine("Sau khi khoi tao: bien = {0}", bien) ;
// Gan gia tri cho bien
bien = 5 ;
// Xuat ra man hinh
System.Console.WriteLine("Sau khi gan: bien = {0}", bien) ;
}
}
1.6. Hằng
1.6.1. Khái niệm
- Hằng cũng là một biến nhưng giá trị của hằng không thay đổi trong khi thực
hiện các lệnh của chương trình.
- Hằng được phân làm 3 loại:
+ Giá trị hằng (literal)
+ Biểu tượng hằng (symbolic constants)
+ Kiểu liệt kê (enumerations)
1.6.2. Giá trị hằng:
Ví dụ: x = 100; // 100 được gọi là giá trị hằng
1.6.3. Biểu tượng hằng
Gán một tên hằng cho một giá trị hằng.
Khai báo:
<const> <Kiểu_Dữ_Liệu> <tên_hằng> = <giá_trị> ;
Ví dụ 1.2: Nhập vào bán kính, in ra chu vi và diện tích hình tròn.
class HinhTron
{

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 13


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

static void Main()


{
// Khai bao bieu tuong hang
const double PI = 3.14159 ;
// Khai bao bien
int bankinh ;
double chuvi , dientich ;
string chuoi ;
// Nhap gia tri cho bien chuoi
System.Console.Write("Nhap ban kinh hinh tron: ") ;
chuoi = System.Console.ReadLine() ;
// Doi chuoi thanh so va gan vao bien so
bankinh = System.Convert.ToInt32(chuoi) ;
// Gan gia tri cho bien
chuvi = 2 * bankinh * PI ;
dientich = bankinh * bankinh * PI ;
// Xuat ra man hinh
System.Console.WriteLine("Chu vi hinh tron = {0:0.00}", chuvi);
System.Console.WriteLine("Dien tich hinh tron = {0:0.00}", dientich);
}
}
1.6.4. Kiểu liệt kê
Là tập hợp các tên hằng có giá trị số không thay đổi (danh sách liệt kê)
Khai báo:
<enum> <Tên_Kiểu_Liệt_Kê>
{
<tên_hằng_1> = <giá_trị_số_1>,
<tên_hằng_2> = <giá_trị_số_2>,
... ,
};
Ví dụ:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 14


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

enum NhietDoNuoc
{
DoDong = 0, DoNguoi = 20,
DoAm = 40, DoNong = 60,
DoSoi = 100,
};
1.7. Toán tử
- Toán tử toán học: + , - , * , / , %
- Toán tử tăng / giảm: += , -= , *= , /= , %=
- Toán tử tăng / giảm 1 đơn vị: ++ , --
- Toán tử gán: =
- Toán tử quan hệ: == , != , > , >= , < , <=
- Toán tử logic: ! , && , ||
- Toán tử 3 ngôi: (Điều_Kiện) ? (Biểu_Thức_1) : (Biểu_Thức_2) ;
1.8. Kiểu dữ liệu
C# chia kiểu dữ liệu thành hai tập hợp kiểu dữ liệu chính:
- Kiểu xây dựng sẵn (built-in): do ngôn ngữ cung cấp cho người lập trình.
- Kiểu do người dùng định nghĩa (user-defined): do người lập trình tạo ra.
1.8.1. Kiểu dữ liệu dựng sẵn
Kiểu C# Số byte Kiểu .NET Mô tả
byte 1 Byte Số nguyên dương không dấu từ 0 đến 255
char 2 Char Ký tự Unicode
bool 1 Boolean Giá trị logic true / false
sbyte 1 Sbyte Số nguyên có dấu từ -128 đến 127
short 2 Int16 Số nguyên có dấu từ -32768 đến 32767
ushort 2 Uint16 Số nguyên dương không dấu từ 0 đến 65535
int 4 Int32 Số nguyên có dấu từ -2.147.483.647 đến
2.147.483.647
uint 4 Uint32 Số nguyên không dấu từ 0 đến 4.294.967.295
float 4 Single Kiểu dấu chấm động, giá trị xấp xỉ từ

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 15


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

-3.4E-38 đến 3.4E+38, với 7 chữ số có nghĩa


double 8 Double Kiểu dấu chấm động có độ chính xác gấp
đôi, giá trị xấp xỉ từ -1.7E-308
đến 1.7E+308, với 15, 16 chữ số có nghĩa
decimal 8 Decimal Có độ chính xác đến 28 con số và giá trị thập
phân, được dùng trong tính toán tài chính,
kiểu này đòi hỏi phải có hậu tố “m” hay “M”
long 8 Int64 Kiểu số nguyên có dấu có giá trị trong
khoảng -9.223.370.036.854.775.808 đến
9.223.372.036.854.775.807
ulong 8 Uint64 Số nguyên không dấu từ 0 đến
0xfffffffffffffff
* Bảng trình bày các ký tự đặc biệt
Ký tự Ý nghĩa
\' Dấu nháy đơn
\" Dấu nháy kép
\\ Dấu chéo
\0 Ký tự null
\a Alert
\b Backspace
\f Sang trang form feed
\n Dòng mới
\r Đầu dòng
\t Tab ngang
\v Tab dọc
1.8.2. Chuyển đổi kiểu dữ liệu
Ví dụ 1:
short x = 10 ;
int y = x ; // chuyển đổi ngầm định
Ví dụ 2:
short x ;
int y = 100 ;
x = (short) y ; // ép kiểu tường minh, trình biên dịch không báo lỗi
Ví dụ 3:
short x ;
int y = 100 ;
x = y ; // không biên dịch, lỗi

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 16


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

CHƯƠNG 2: CẤU TRÚC ĐIỀU KHIỂN


2.1. Giới thiệu
Khi xây dựng ứng du ̣ng viế t bởi ngôn ngữ lâ ̣p triǹ h C#, chúng ta thường phải
ứng du ̣ng các kỹ thuâ ̣t cũng như khái niê ̣m của lâ ̣p triǹ h hướng đố i tươ ̣ng để triể n
khai các lớp (Class), các giao diê ̣n (Interface), các công cu ̣ (Library, User control, …)
cầ n thiế t cho chương trình của mình.
Để thực hiê ̣n những điề u này, ba ̣n buô ̣c phải nắ m vững những khái niê ̣m cơ bản
có liên quan đế n viê ̣c sử du ̣ng biế n (Variable), hằ ng (Constant), các kỹ thuâ ̣t cơ bản
hỗ trơ ̣ cho quá triǹ h xây dựng mã lê ̣nh. Mô ̣t trong những kỹ năng cầ n có chiń h là phải
hiể u rõ và sử du ̣ng các cấ u trúc điề u khiể n chương triǹ h của C# mô ̣t cách thuầ n thu ̣c.
C# cung cấ p khá đa da ̣ng và linh hoa ̣t các cấ u trúc điề u khiể n cơ bản để lâ ̣p trình
viên có thể sử du ̣ng khi viế t mã lê ̣nh, các cấ u trúc lê ̣nh này thông thường đươ ̣c chia
làm 3 nhóm như sau:
- Các cấ u trúc lựa cho ̣n để thực thi lê ̣nh theo tin
̀ h huố ng (Selection constructs):
với mu ̣c đích làm cho khả năng thực thi của chương trình đươ ̣c linh hoa ̣t
chúng ta sẽ sử du ̣ng cấ u trúc da ̣ng này. Ứng với mỗi tiǹ h huố ng khác nhau
sẽ có những cách giải quyế t khác nhau, các lê ̣nh thuô ̣c da ̣ng này thường thấ y:
if …; if … else …; switch … (Các cấ u trúc thuô ̣c da ̣ng này còn đươ ̣c go ̣i với
cu ̣m từ : “Cấ u trúc rẽ nhánh”).
- Các cấ u trúc lă ̣p để thực thi các lê ̣nh theo chu kỳ (Loop constructs): Khi có
1 hoă ̣c nhiề u lê ̣nh cầ n phải thực thi nhiề u lầ n, chúng ta sẽ sử du ̣ng đế n cấ u
trúc lă ̣p trong chương trin ̀ h của miǹ h. Thường thì cấ u trúc lă ̣p trong các ngôn
ngữ lâ ̣p triǹ h hiê ̣n đa ̣i thường chia làm 3 da ̣ng: lă ̣p với số lầ n xác đinh,̣ không
xác đinh ̣ và lă ̣p trên 1 tâ ̣p hơ ̣p các phầ n tử (Ở đây ta hiể u số lầ n lă ̣p xác đinh
̣
và không xác đinh ̣ là đố i với trước khi thực hiê ̣n quá triǹ h lă ̣p, còn di ̃ nhiên
sau khi đã thực hiê ̣n xong thì đã biế t chiń h xác ta ̣i thời điể m đó lă ̣p bao nhiêu
lầ n rồ i). Các cấ u trúc lă ̣p mà chúng ta sẽ sử du ̣ng trong C#: for …, do …
while, while …, foreach …
- Các cấ u trúc lê ̣nh “Jump” (Jump constructs): Như chúng ta biế t, mă ̣c nhiên
thì quá trình thực thi các lê ̣nh trong chương triǹ h sẽ là “tuầ n tự, liên tu ̣c”.
Tức là khi chương trình thi hành, các lê ̣nh sẽ thực thi từ trên xuố ng dưới, từ
trái qua phải, hế t lê ̣nh này sẽ thực thi đế n lê ̣nh kế tiế p. Tuy nhiên, trong
những tiǹ h huố ng nào đó, sau khi thi hành đế n lê ̣nh thứ n thì không cầ n thiế t
phải thực thi những lê ̣nh còn la ̣i nữa bởi vì đế n đó, bài toán đã đươ ̣c giải
quyế t, viê ̣c thực thi các lê ̣nh còn la ̣i là dư thừa. Để giải quyế t vấ n đề này, C#
cung cấ p cho chúng ta các lê ̣nh: break, continue, return, goto, …

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 17


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Ở trên, chúng ta đã tóm lươ ̣c những ý chiń h mô tả cho mu ̣c tiêu của bài viế t này.
Bây giờ, chúng ta sẽ làm quen với cả 3 da ̣ng cấ u trúc lê ̣nh như đã giới thiê ̣u.
2.2. Câu lệnh if … else
- Công dụng:
Câu lệnh if cho phép bạn thực thi một khối đoạn code giá trị được chỉ định
là điều kiện logic .Câu lệnh bắt đầu với từ khóa if và sau đó là điều kiện. nếu
giá trị của điều kiện là đúng khối câu lệnh sau if được thực hiện. Khối câu lệnh
sau if được bỏ qua và khối câu lệnh sau đó được thực hiện.
- Cú pháp:
if (Điều_Kiện)
<Khối lệnh Điều_Kiện đúng>
[else
<Khối lệnh Điều_Kiện sai>]
- Ví dụ: Dùng câu lệnh điều kiện if … else
using System;
class Chan_Le
{
static void Main()
{
// Khai bao va khoi tao bien
int bienDem = 9 ;
// Xuat ra man hinh
if (bienDem % 2 == 0)
Console.WriteLine("{0} la so chan", bienDem) ;
else Console.WriteLine("{0} la so le", bienDem) ;
}
}
2.3. Câu lệnh if lồng nhau
- Công dụng:
Sử dụng khi có nhiều điều kiện if . Câu lệnh if lồng bắt đầu với từ khóa if và
cũng kết thúc với từ khóa if. Mỗi một khối điều kiện if lằm một nhiệm vụ
kiểm tra riêng nhưng vẫn liên quan đến nhau.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 18


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

- Cú pháp:
if (Điều_Kiện_1)
<Khối lệnh 1>
else if (Điều_Kiện_2)
<Khối lệnh 2.1>
else
<Khối lệnh 2.2>
- Ví dụ:
using System;
class Thu_Trong_Tuan
{
static void Main()
{
// Khai bao va khoi tao bien
int thu = 5 ; // 0: Chu nhat, 1: Thu hai, 2: Thu ba, 3: Thu tu,
// 4: Thu nam, 5: Thu sau, 6: Thu bay
// Xuat ra man hinh
if ((thu == 1) || (thu == 3) || (thu == 5))
Console.WriteLine("Day la ngay 2-4-6") ;
else if ((thu == 2) || (thu == 4) || (thu == 6))
Console.WriteLine("Day la ngay 3-5-7") ;
else Console.WriteLine("Day la ngay chu nhat") ;
}
}
2.4. Câu lệnh switch
switch (Biểu_Thức)
{
case <giá_trị_1>:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 19


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

< Khối lệnh 1>


<Lệnh Nhảy>
case <giá_trị_2>:
< Khối lệnh 2>
<Lệnh Nhảy>
….
[default:
< Khối lệnh khác>]
}
2.5. Cấu trúc lặp
Vòng lặp cho phép thực thi một khối các câu lệnh hoặc một câu lệnh đơn lặp
lại. Hầu hết sử dụng vòng lặp để hiển thị một dãy các số có đặc trưng lặp đi lặp lại.
Trong mỗi chương trình phần mềm vòng lặp bao gồm một điều kiện giúp cho
trình biên dịch xác định được số lần cần lặp lại và khối lệnh đó được thực thi. Nếu số
lần lặp lại không được chỉ định vòng lặp sẽ là vĩnh viễn.
2.5.1. While
- Công dụng:
+ Vòng lặp while thực hiện một khối của đoạn mã bắt đầu với từ khóa while
trong đó là điều kiện giá tri boolean. Nếu điều kiện là true vòng lặp tiếp tục thực hiện
khối câu lệnh nếu là false vòng lặp kết thúc.
+ Vòng lặp while luôn kiểm tra trước khi thực hiện vòng lặp.
- Cú pháp:
while (Điều_Kiện)
< Khối lệnh>
- Ví dụ:
using System;
class UsingWhile
{
static void Main()
{
// Khai bao va khoi tao bien dem
int i = 1 ;

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 20


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

// Xuat ra man hinh


while (i<=10) {
Console.WriteLine("i = {0}",i) ;
i++ ; // tang bien dem,
}
}
}
2.5.2. Do … while
- Công dụng:
Vòng lặp do - while tương tự như vòng lặp , khác ở chỗ là kiểm tra điều kiện
sau khi đã thực hiện khối lệnh 1 lần rồi mới kiểm tra điều kiện. Nếu đúng thì tiếp tục
lặp lại khối lệnh, nếu sai thoát khỏi vòng lặp.
- Cú pháp:
do
< Khối lệnh>
while (Điều_Kiện) ;
- Ví dụ:
using System;
class UsingDoWhile
{
static void Main()
{
// Khai bao va khoi tao bien dem
int i = 1 ;
// Xuat ra man hinh
do {
Console.WriteLine("i = {0}",i) ;
i++ ; // tang bien dem
} while (i<= 10) ;

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 21


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

}
}
2.5.3. For
- Công dụng:
Tương tự như vòng lặp while trong hàm của nó .Thân của hàm sẽ được thực
hiện nếu điều kiện đúng.
- Cú pháp:
for ([Khởi_tạo] ; [Điều_kiện] ; [Bước_lặp])
< Khối lệnh>
- Ví dụ:
using System;
class UsingFor
{
static void Main()
{
for (int i=1 ; i<=30 ; i++)
if (i % 10 ==0)
Console.Write("{0} \n\r",i) ;
else Console.Write("{0} ",i) ;
}
}
2.5.4. Foreach
- Công dụng:
Thực hiện một khối các câu lệnh cho mỗi một giá trị trong danh sách chỉ
định giá trị điều kiện ở đây không xác định được. Các giá trị đựợc chỉ định trong
vòng foreach chỉ có thể đọc không thể thay đổi value của chúng.
- Cú pháp:
foreach (<Kiểu_tập_hợp> <Tên_truy_cập_thành_phần> in <Tên_tập_hợp>)
< Khối lệnh>
- Ví dụ:
using System;

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 22


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

public class UsingForeach


{
public static void Main()
{
int[] intArray = {1,2,3,4,5,6,7,8,9,10};
foreach (int item in intArray)
Console.WriteLine("i = {0} ",item) ;
}
}

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 23


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

BÀI TẬP CHƯƠNG 1


Câu 1: Thiết kế màn hình tìm số lớn nhất a và b

Câu 2: Thiết kế màn hình chào theo giờ

Câu 3: Thiết kế màn hình kết quả học tập

Câu 4: Thiết kế màn hình điểm thi đại học

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 24


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Câu 5: Thiết kế màn hình giải phương trình bậc nhất

Câu 6: Thiết kế màn hình tính tiền hát Karaoke

Câu 7: Thiết kề màn hình nhận dạng tam giác

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 25


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Câu 8: Thiết kế màn hình đọc số

Câu 9: Thiết kế màn hình tính toán dãy số

Câu 10: Thiết kế màn hình tìm ước số chung lớn nhất

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 26


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 27


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

CHƯƠNG 3: DỮ LIỆU KIỂU MẢNG


3.1. Mảng 1 chiều
3.1.1. Định nghĩa
- Mảng là một tập hợp có thứ tự của những đối tượng (objects), tất cả các đối
tượng này có cùng một kiểu dữ liệu.
- Mảng trong ngôn ngữ C# sử dụng những phương thức và các thuộc tính. Thể
hiện của mảng trong C# có thể truy cập những phương thức và các thuộc tính của
System.Array.
- Một số các thuộc tính và phương thức của lớp System.Array:
Thành viên Mô tả
Sort() Phương thức sắp xếp giá trị tăng dần trong mảng một chiều
Reverse() Phương thức sắp xếp giá trị giảm dần trong mảng một chiều
Length Thuộc tính chiều dài của mảng
SetValue() Phương thức thiết lập giá trị cho một thành phần xác định trong mảng
3.1.2. Khai báo mảng:
<kiểu dữ liệu>[] <tên mảng> ;
Ví dụ:
int[] myIntArray ;
Tạo thể hiện của mảng: sử dụng từ khóa new
Ví dụ:
myIntArray = new int[5] ;
3.1.3. Khởi tạo thành phần của mảng
- Tạo thể hiện của mảng đồng thời với khởi tạo các giá trị:
+ Cách 1:
int[] myIntArray = new int[5] {2, 4, 6, 8, 10};
+ Cách 2:
int[] myIntArray = {2, 4, 6, 8, 10};
Các khai báo trên sẽ thiết lập bên trong bộ nhớ một mảng chứa 5 số nguyên.
Chú ý: Không thể thiết lập lại kích thước cho mảng.
3.1.4. Giá trị mặc định:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 28


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

- Khi chúng ta tạo một mảng có kiểu dữ liệu giá trị, mỗi thành phần sẽ chứa giá
trị mặc định của kiểu dữ liệu.
Ví dụ:
Với khai báo int myIntArray = new int[5] ; thì:
- Mỗi thành phần của mảng được thiết lập giá trị là 0 (giá trị mặc định của số
nguyên).
- Những kiểu tham chiếu trong một mảng không được khởi tạo giá trị mặc
định, chúng được khởi tạo giá trị null.
3.1.5. Truy cập các thành phần trong mảng:
- Để truy cập vào thành phần trong mảng ta sử dụng toán tử chỉ mục ([]).
- Chỉ mục của thành phần đầu tiên trong mảng luôn luôn là 0.
- Thuộc tính Length của mảng cho biết số đối tượng trong một mảng.
3.1.6. Duyệt mảng 1 chiều:
for (int i=0; i < myIntArray.Length; i++) {
xử lý myIntArraya[i];
}
Có thể thay for bằng foreach như sau
foreach (int phantu in a){
xử lý myIntArraya[i];
}
Ví dụ: (Mảng 5 số nguyên từ 1 đến 5)
* Khởi tạo một ứng dụng Windows Forms Application, lưu với tên là Vi Du
như sau:

* Yêu cầu
- Thiết kế form như mẫu (lblKQ, btnIn, btnXoa, btnDung).

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 29


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

- Khai báo mảng 1 chiều (a) gồm 5 số nguyên từ 1 đến 5.


- Nhắp vào button In mảng (btnIn) sẽ in ra label (lblKQ) các giá trị trong
mảng.
- Nhắp vào button Xóa (btnXoa) sẽ xóa trống nội dung của label (lblKQ).
- Nhắp vào button Dừng sẽ dừng chương trình.
* Hướng dẫn
- Thiết kế form như yêu cầu.
- Khai báo mảng: qua code, thêm đoạn code để được kết quả như sau:
public partial class Form1 : Form
{
// Khai bao mang 1 chieu gom 5 so nguyen tu 1 den 5
int[] a = { 1, 2, 3, 4, 5 };
}
- Nhắp đúp vào button In mảng, thêm đoạn code sau:
// Xuat cac phan tu trong mang ra man hinh this.lblKQ.Text="Các phần tử
trong mảng là:\n\r";
for (int i=0; i < a.Length; i++) {
this.lblKQ.Text += a[i]+" ";
}
Có thể thay for bằng foreach như sau
foreach (int phantu in a){
this.lblKQ.Text += a[i]+" ";
}
- Nhắp đúp vào button Xóa, thêm đoạn code sau:
this.lblKQ.Text = "";
- Nhắp đúp vào button Dừng, thêm đoạn code sau:
Application.Exit();
Ví dụ: (Mảng 5 số nguyên)
* Khởi tạo một ứng dụng Windows Forms Application, lưu với tên là Vi Du
như sau:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 30


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

* Yêu cầu
- Thiết kế form: btnNhap, txtNhap, btnTang, btnGiam, lblKQ, btnIn,
btnXoa, btnDung.
- Khai báo mảng 1 chiều (a) chứa 5 số nguyên, số phần tử hiện có (sopt)
là 0.
- Nhập số vào TextBox txtNhap, nhắp vào button Nhập 1 phần tử mảng
(btnNhap) cho phép đưa giá trị trong TextBox txtNhap vào mảng. Khi
mảng đã đủ 5 số nguyên thì phải thông báo “Mảng đã đầy” và không
cho nhập nữa.
- Nhắp vào button Sắp tăng (btnTang) sẽ sắp xếp mảng theo thứ tự tăng
dần.
- Nhắp vào button Sắp giảm (btnGiam) sẽ sắp xếp mảng theo thứ tự giảm
dần.
- Nhắp vào button In mảng (btnIn) sẽ in ra label (lblKQ) các giá trị trong
mảng.
- Nhắp vào button Xóa (btnXoa) sẽ xóa trống nội dung của label (lblKQ)
đồng thời khai báo lại số phần tử hiện có (sopt) của mảng là 0.
- Nhắp vào button Dừng sẽ dừng chương trình.
* Hướng dẫn
- Thiết kế form như yêu cầu.
- Khai báo mảng như sau:
public partial class Form1 : Form
{
// Khai bao mang 1 chieu gom 5 so nguyen int[] a = new int[5];
// Khai bao so phan tu hien co cua mang int sopt = 0;
}
- Nhắp đúp vào button Nhập 1 phần tử mảng, thêm đoạn code sau:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 31


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

// Nhap mot phan tu cho mang if (sopt == 5)


MessageBox.Show("Mảng đã đầy!");
else
{
a[sopt] = Convert.ToInt32(this.txtNhap.Text);
sopt++;
this.txtNhap.ResetText();
this.txtNhap.Focus();
}
- Nhắp đúp vào button Sắp tăng, thêm đoạn code sau:
// Sap xep mang giam
if (sopt == 0)
this.lblKQ.Text = "Mảng rỗng!";
else
Array.Sort(a, 0, sopt);
this.lblKQ.Text = "Đã sắp xếp mảng tăng dần!";
- Nhắp đúp vào button Sắp giảm, thêm đoạn code sau:
// Sap xep mang giam
if (sopt == 0)
this.lblKQ.Text = "Mảng rỗng!";
else
Array.Reverse(a, 0, sopt);
this.lblKQ.Text = "Đã sắp xếp mảng giảm dần!";
- Nhắp đúp vào button Xóa, thêm đoạn code sau:
this.lblKQ.Text = ""; sopt = 0; this.txtNhap.Focus();
- Nhắp đúp vào button In mảng, thêm đoạn code sau:
// Xuat cac phan tu trong mang ra man hinh
if (sopt==0)
this.lblKQ.Text = "Mảng rỗng!";
else
{

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 32


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

this.lblKQ.Text="Các phần tử trong mảng là:\n\r";


for (int i = 0; i < sopt; i++)
this.lblKQ.Text += a[i] + " ";
}
- Nhắp đúp vào button Dừng, thêm đoạn code sau:
Application.Exit();

3.2. Mảng nhiều chiều


3.2.1. Định nghĩa
- Mảng đa chiều là mảng mà mỗi thành phần là một mảng khác.
- Ngôn ngữ C# hỗ trợ hai kiểu mảng đa chiều là:
+ Mảng đa chiều cùng kích thước.
+ Mảng đa chiều khác kích thước.
- Trong phạm vi bài học này, ta chỉ khảo sát mảng 2 chiều mà thôi.
3.2.2. Khai báo mảng 2 chiều
<kiểu dữ liệu>[ , ] <tên mảng>
Ví dụ:
int[ , ] myRectangularArray ;
3.2.3. Khởi tạo thành phần của mảng
int[] myRectangularArray = new int[sodong , socot] ;
3.2.4. Duyệt mảng 2 chiều
for (int i = 0; i < sodong; i++)
{
for (int j = 0; j < socot; j++)
{
Xử lý myRectangularArray[i,j];
}
}

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 33


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Ví dụ: Khởi tạo một ứng dụng Windows Forms Application, lưu với tên là Vi
Du như sau:

* Yêu cầu
- Thiết kế form như mẫu (lblKQ, btnIn, btnXoa, btnDung, btnNhap,
btnSapXep).
- Khai báo mảng 2 chiều gồm 4 dòng, 3 cột chứa các số nguyên.
- Nhắp vào button Nhập mảng để nhập các phần tử cho mảng (có giá trị =
dòng - cột).
- Nhắp vào button Sắp Xếp sẽ sắp xếp mảng tăng dần theo từng hàng.
- Nhắp vào button In mảng (btnIn) sẽ in ra label (lblKQ) các giá trị trong
mảng.
- Nhắp vào button Xóa (btnXoa) sẽ xóa trống nội dung của label (lblKQ).
- Nhắp vào button Dừng sẽ dừng chương trình.
* Hướng dẫn
- Thiết kế form như yêu cầu.
- Khai báo mảng: qua code, thêm đoạn code để được kết quả như sau:
public partial class Form1 : Form
{
// Khai bao 4 dong 3 cot const int sodong = 4; const int socot = 3;
// Khai bao mang 2 chieu gom 4 dong, 3 cot chua 12 so nguyen
int[,] Array2 = new int[sodong,socot];
}
- Nhắp đúp vào button Nhập mảng, thêm đoạn code sau:
// Nhap cac phan tu cho mang
for (int i=0; i < sodong; i++)

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 34


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

for (int j=0; j< socot; j++)


Array2[i,j]= i-j;
- Nhắp đúp vào button Sắp xếp, thêm đoạn code sau:
// Sap xep mang
int[] t = new int[sodong * socot];
for (int i = 0; i < sodong; i++)
{
for (int j = 0; j < socot; j++)
t[j] = Array2[i, j];
Array.Sort(t, 0, socot);
for (int j = 0; j < socot; j++)
Array2[i, j]=t[j];
}
- Nhắp đúp vào button In mảng, thêm đoạn code sau:
// Xuat cac phan tu trong mang ra man hinh this.lblKQ.Text = "Các phần
tử trong mảng là:\n\r";
for (int i = 0; i < sodong; i++)
{
for (int j = 0; j < socot; j++)
{
this.lblKQ.Text += Array2[i,j] + " ";
}
this.lblKQ.Text += "\n\r";
}
- Nhắp đúp vào button Xóa, thêm đoạn code sau:
this.lblKQ.Text = "";
- Nhắp đúp vào button Dừng, thêm đoạn code sau:
Application.Exit();
3.3. Exception (Ngoại lệ)

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 35


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

3.3.1. Khái niệm


- Exception có thể được hiểu là bắt giữ lỗi với những đoạn mã hợp lệ để không
tổn hại đến chương trình.
- Lỗi có thể do nguyên nhân từ chính người sử dụng; hoặc có thể do những vấn
đề không mong đợi khác như: thiếu bộ nhớ, thiếu tài nguyên hệ thống ….
- Một trình xử lý ngoại lệ là một khối lệnh chương trình được thiết kế xử lý các
ngoại lệ mà chương trình phát sinh.
- Xử lý ngoại lệ được thực thi trong trong câu lệnh catch.
- Các câu lệnh có khả năng xảy ra ngoại lệ thực thi trong câu lệnh try.
* Một cách lý tưởng, nếu một ngoại lệ được bắt và được xử lý thì chương trình
có thể sửa chữa được vấn đề bị lỗi và tiếp tục thực hiện hoạt động. Thậm chí nếu
chương trình không tiếp tục, bằng việc bắt giữ ngoại lệ chúng ta cũng có cơ hội để in
ra những thông điệp có ý nghĩa và kết thúc chương trình một cách rõ ràng.
3.3.2. Ví dụ
* Khởi tạo một ứng dụng Windows Forms Application, lưu với tên là Vi Du
như sau:

* Yêu cầu
- Thiết kế form gồm: lbl1, txtSo1, lbl2, txtSo2, lbl3, txtKQ và các button (xem
hình).
- Nhập số vào 2 TextBox txtSo1 và TxtSo2.
- Nhắp vào button Chia:
+ Nếu txtSo1, txtSo2 không phải là số; hoặc nhập vào txtSo2 là 0 thì báo
lỗi: “Lỗi rồi!”.
+ Nếu txtSo1, txtSo2 là số thì xuất kết quả là txtSo1 / txtSo2 vào TextBox
txtKQ.
- Nhắp button Xóa thì xóa trống: TextBox txtS1, TextBox txtS2, Label lblKQ
đồng thời đưa con trỏ vào TextBox txtS1.
- Nhắp buuton Dừng thì dừng chương trình.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 36


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

* Hướng dẫn
- Thiết kế form như yêu cầu.
- Nhắp đúp vào button Chia, thêm vào đoạn code:
// Xóa trống TextBox txtKQ
txtKQ.ResetText();
// Đoạn code có xảy ra ngoại lệ khi thực hiện
try
{
int so1 = int.Parse(this.txtSo1.Text); int so2 = int.Parse(this.txtSo2.Text);
this.txtKQ.Text += (float)so1 / so2;
}
// Xử lý ngoại lệ
catch (Exception ex)
{
}

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 37


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

BÀI TẬP CHƯƠNG 3


Câu 1: Thiết kế màn hình xử lý mảng

Câu 2: Thiết kế màn hình như sau:


- Sau khi phát sinh mảng

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 38


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

- Sau khi sắp xếp tăng

- Sau khi sửa đổi giá trị của phần từ

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 39


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 40


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

CHƯƠNG 4: CLASS - OBJECT – METHOD


4.1. Khái niệm

- Kiểu dữ liệu trong C# được định nghĩa là một lớp (class).


- Thể hiện riêng của từng lớp được gọi là đối tượng (object).
- Hai thành phần chính cấu thành một lớp (class) là thuộc tính / tính chất và
phương thức (method) / hành động ứng xử của đối tượng.
4.2. Định nghĩa lớp (class)
4.2.1. Cú pháp
[Thuộc tính] [Bổ sung truy cập] class <Tên lớp> [: Lớp cơ sở]
{
// Các thuộc tính
<Thuộc tính>
// Các phương thức
<Phương thức>
}
4.2.2. Ví dụ
* Khởi tạo một ứng dụng Windows Forms Application, lưu với tên là Vi Du
như sau:

* Yêu cầu
- Thiết kế form gồm: lbl1, txtHoTen, lbl2, lblKQ, và các button (xem hình).

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 41


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

- Tạo class Chuoi như sau:


public class Chuoi
{
// Thuộc tính
...
// Phương thức
...
}
+ Trong phần thuộc tính, khai báo:
string tenchuongtrinh = "Chương trình xử lý họ và tên!";
+ Trong phần phương thức, khai báo các phương thức sau:
// Phương thức
public string In()
{
// In tên chương trình
return tenchuongtrinh;
}
public string Ten(string hoten)
{
// Lấy tên
int lio=hoten.LastIndexOf(" ");
return hoten.Substring(lio+1, hoten.Length-lio-1);
}
public string HoLot(string hoten)
{
// Lấy họ và lót
int lio = hoten.LastIndexOf(" ");
return hoten.Substring(0,lio);
}
public int CountOfWord(string hoten)
{

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 42


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

// Đếm số từ trong chuỗi


// Tạo ra hằng ký tự khoảng trắng
const char Space =' ';
// Gán giá trị cho chuỗi
string s = hoten.Trim();
// Thực hiện việc chia chuỗi thành mảng --> Đếm từ
cWord = s.Split(Space)).Length ;
// Gởi kết quả trả về
return cWord;
}
** Tham khảo thêm đoạn code sau:
// Đếm số từ trong chuỗi HoTen
int count = 0;
string s = hoten.Trim();
for (int i = 0; i < s.Length - 1; i++)
if ((s.Substring(i,1)==" ")&&(s.Substring(i+1,1)!= " "))
count++; if (s.Length > 0) count++;
return count;
public string Proper(string hoten)
{
// Đổi thành chữ Hoa Đầu Từ trong chuỗi txtHoTen
// Tạo ra hằng ký tự khoảng trắng
const char Space = ' ';
// Gán giá trị cho chuỗi
string s = hoten.Trim();
// Đổi chuỗi
string kq = "Chuỗi rỗng!";
if (s.Length == 0)
return kq;

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 43


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

else
{
kq = "";
string [] s1 = s.Split(Space);
foreach (string tu in s1) {
string vss = tu[0].ToString();
kq += ss.ToUpper();
kq += tu.Substring(1,tu.Length-1);
kq += " ";
}
return kq.Trim();
}
** Tham khảo thêm đoạn code sau:

// Đổi thành chữ Hoa Đầu Từ trong chuỗi txtHoTen


string s = hoten.Trim();
string kq = "Chuỗi rỗng!";
if (s.Length > 0)
{
kq = s.Substring(0, 1).ToUpper();
for (int i = 1; i < s.Length; i++)
{
if ((s[i - 1].ToString() == " ") && (s[i].ToString() != " "))
{
string ss = s[i].ToString();
kq += ss.ToUpper();
}
else
kq += s[i].ToString();
}
}

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 44


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

return kq;
- Sử dụng các phương thức trên để thực hiện các việc sau đây (xuất kết quả
trong lblKQ):
+ Nhắp vào button In Lời giới thiệu, sẽ in lời giới thiệu.
+ Nhắp button Họ Lót, tách lấy họ lót của chuỗi trong txtHoTen.
+ Nhắp button Tên, tách lấy tên của chuỗi trong txtHoTen.
+ Nhắp button Đếm từ, đếm số từ của chuỗi trong txtHoTen.
+ Nhắp button Hoa Đầu Từ, đổi thành chuỗi Hoa Đầu Từ của chuỗi trong
txtHoTen.
- Nhắp button Xóa thì xóa trống: TextBox txtHoTen, Label lblKQ đồng thời
đưa con trỏ vào TextBox txtHoTen.
- Nhắp button Dừng thì dừng chương trình.
* Hướng dẫn
- Thiết kế form như yêu cầu.
- Khai báo class: qua code, thêm đoạn code để được kết quả như sau
public Form1()
{
InitializeComponent();
}
public class Chuoi
{
// Thuộc tính
... (1)
// Phương thức
... (2)
}
+ Trong phần (1), khai báo thuộc tính (xem đề bài)
+ Trong phần (2), khai báo phương thức (xem đề bài)
- Nhắp đúp vào button In Lời giới thiệu, thêm vào đoạn code:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 45


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Chuoi s = new Chuoi();


this.lblKQ.Text = s.In();
- Nhắp đúp vào button Họ lót, thêm vào đoạn code:
Chuoi s = new Chuoi();
this.lblKQ.Text="Họ lót: " + s.HoLot(this.txtHoTen.Text);
- Nhắp đúp vào button Tên, thêm vào đoạn code:
Chuoi s = new Chuoi();
this.lblKQ.Text = "Tên là: " + s.Ten(this.txtHoTen.Text);
- Nhắp đúp vào button Đếm từ, thêm vào đoạn code:
Chuoi s = new Chuoi();
this.lblKQ.Text = "Tổng số từ là: " ;
this.lblKQ.Text += s.CountOfWord(this.txtHoTen.Text);
- Nhắp đúp vào button Hoa Đầu Từ, thêm vào đoạn code:
Chuoi s = new Chuoi();
this.lblKQ.Text = "Kết quả là: " ;
this.lblKQ.Text += s.Proper(this.txtHoTen.Text);
- Nhắp đúp vào button Xóa, thêm vào đoạn code:
this.lblKQ.Text = ""; this.txtHoTen.ResetText(); this.txtHoTen.Focus();
- Nhắp đúp vào button Dừng, thêm vào đoạn code:
Application.Exit();
* Bổ sung
- Nút button In Hoa: đổi thành chuỗi IN HOA của chuỗi trong txtHoTen .
- Nút button In Thường: đổi thành chuỗi in thường của chuỗi trong
txtHoTen.
4.3. Properties - Method
4.3.1. Thuộc tính (Properties)
Thuộc tính là những thông tin có thể thay đổi được.
4.3.2. Thuộc tính truy cập
Thuộc tính Giới hạn truy cập

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 46


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

public Không hạn chế. Những thành viên được đánh dấu public có
thể được dùng bất kỳ các phương thức của lớp, bao gồm cả
những lớp khác.
private Thành viên trong lớp được đánh dấu private chỉ được dùng
các phương thức của lớp này mà thôi.
Protected Thành viên trong lớp được đánh dấu protected chỉ được dùng
các phương thức của lớp này; và các phương thức của lớp dẫn
xuất từ lớp này.
Internal Thành viên trong lớp được đánh dấu là internal được dùng
các phương thức của bất kỳ lớp nào cùng khối hợp ngữ với
lớp này.
protected internal Thành viên trong lớp được đánh dấu là protected internal
được dùng các phương thức của lớp này; các phương thức của
lớp dẫn xuất từ lớp này; và các phương thức của bất kỳ lớp
nào trong cùng khối hợp ngữ với lớp này.
4.3.3. Phương thức (Method)
- Phương thức (method) chính là các hàm (function) được tạo trong lớp (class).
- Tên của phương thức thường được đặt theo tên của hành động.
4.3.4. Tham số của phương thức
- Các tham số theo sau tên phương thức và được bọc bên trong dấu ngoặc tròn
().
- Mỗi tham số phải khai báo kèm theo kiểu dữ liệu.
- Trong C# có 2 dạng truyền tham số:
+ Truyền tham chiếu: dùng thêm từ khóa ref.
+ Truyền tham trị
Ví dụ:
* Truyền tham số cho phương thức theo kiểu tham chiếu
public class Hoandoi
{
public void HoanVi(ref int a, ref int b)
{
int c = a ;
a=b;

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 47


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

b=c;
}
}
Khi đó: khi gọi hàm HoanVi ta phải truyền tham số dưới dạng tham chiếu như
sau:
HoanDoi s = new HoanDoi();
s.HoanVi(ref a, ref b);
* Truyền tham số cho phương thức theo kiểu tham trị
public class HoanDoi
{
public void HoanVi(int a, int b)
{
int c = a ;
a=b;
b=c;
}
}
4.3.5. Ví dụ
* Khởi tạo một ứng dụng Windows Forms Application, lưu với tên là Vi Du
như sau:

* Yêu cầu
- Thiết kế form gồm: lbl1, txta, lbl2, txtb, và các button (xem hình).
- Tạo các class HoanDoi, trong class có hàm HoanVi cho phép hoán
vị 2 giá trị số
nguyên.
- Nhắp button Hoán Đổi sẽ hoán đổi 2 giá trị trong txta và txtb
- Nhắp button Xóa sẽ xóa trống 2 TextBox và đưa con trỏ vào ô txta.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 48


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

- Nhắp button Dừng sẽ dừng chương trình.


* Hướng dẫn
- Thiết kế form như yêu cầu.
- Khai báo class: qua code, thêm đoạn code để được kết quả như sau
public Form1()
{
InitializeComponent();
}
public class HoanDoi
{
public void HoanVi(ref int a,ref int b)
{
int c = a ;
a=b;
b=c;
}
}
- Nhắp đúp vào button Hoán đổi, thêm vào đoạn code:
int a = int.Parse(this.txta.Text);
int b = int.Parse(this.txtb.Text);
HoanDoi s = new HoanDoi();
s.HoanVi(ref a, ref b);
this.txta.Text = a.ToString();
this.txtb.Text = b.ToString();
- Nhắp đúp vào button Xóa, thêm vào đoạn code:
this.txta.ResetText(); this.txtb.ResetText(); this.txta.Focus();
- Nhắp đúp vào button Dừng, thêm vào đoạn code:
Application.Exit();

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 49


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

BÀI TẬP CHƯƠNG 4

Câu 1: Thiết kế màn hình nhập liệu xử lý phân số

Câu 2: Thiết kế màn hình các đối tượng hình học

Câu 3: Thiết kế màn hình nhân viên

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 50


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 51


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

CHƯƠNG 5: LẬP TRÌNH ĐIỀU KHIỂN FORM


5.1. Giới thiệu
Các ứng dụng Windows Form giao tiếp với người dùng thông qua các biểu mẫu
(hay còn gọi là cửa sổ, xuất phát từ chữ Form hay Windows); các điều khiển (Control)
được đặt lên bên trên giúp cho biểu mẫu thực hiện được công việc đó. Biểu mẫu là
các cửa sổ được lập trình nhằm hiển thị dữ liệu và nhận thông tin từ phía người dùng.
Mỗi biểu mẫu và điều khiển đều có các thuộc tính, phương thức và sự kiện gắn
liền với chúng. Thuộc tính bao gồm các đặc trưng của một điều khiển; chúng góp
phần tạo nên dáng vẻ riêng của điều khiển đó. Các thuộc tính có thể được thiết lập ở
thời điểm thiết kế hoặc có thể thiết lập ở thời điểm chạy chương trình bằng cách xây
dựng các câu lệnh (code) thích hợp. Phương thức là các tác vụ mà điều khiển có thể
thực thi; thông thường là các hàm và thủ tục. Sự kiện hay sự kiện là hành động của
người dùng tác động lên điều khiển ở thời điểm chạy chương trình. Một ứng dụng
Windows thường được thực hiện nhờ vào việc đáp ứng lại các sự kiện của người
dùng.
5.1.1. Thuộc tính, sự kiện và phương thức của biểu mẫu
5.1.1.1. Thuộc tính của biểu mẫu
Tên Ý nghĩa
Name Tên để gọi trong chương trình của form. Không sử dụng dấu cách
và các ký tự đặc biệt
AccepButton Tên nút lệnh sẽ được kích hoạt khi người sử dụng gõ Enter
Autosize Tự động thay đổi kích cỡ
BackColor Màu nền form
BackGroundImage Ảnh nền form
Cancel Button Tên nút lệnh sẽ được kích hoạt khi người sử dụng gõ ESC
ContextMenuStript Tên menustrip xuất hiện khi người sử dụng nhấn phải chuột vào đối
tượng
ControlBox True/False - Hiển thị hoặc không hiển thị hộp Control của form
Cussor Thay đổi hình dạng hiển thị của con trỏ chuột khi người sử dụng di
chuyển chuột trên phạm vi điều khiển
Enabled Ngầm định là True, cho phép điều khiển đáp ứng các sự kiện
Font Tên font

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 52


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Tên Ý nghĩa
ForeColor Màu font
FormBorderStyle Kiểu đường viền và tiêu đề Form. Nếu là fixed thì không cho phép
thay đổi kích cỡ
HelpButton Ngầm định là False - không hiển thị nút Help trên form
Icon Biểu tượng trên thanh tiêu đề
IsMidiContainer Ngầm định là False - Form không phải là form MDI
KeyPreview Ngầm định là False - Không cho phép điều khiển các sự kiện bàn
phím
Locked Ngầm định là False - Không cho phép di chuyển hoặc thay đổi kích
cỡ điều khiển khi đang chạy chương trình
MaximizeBox Có hiển thị nút Max của form hay không
MinimizeBox Có hiển thị nút Min của form hay không
StartPosition Vị trí của form khi được kích hoạt
ShowIcon Cho phép hiện/ẩn Icon
Text Nội dung thanh tiêu đề
TopMost Form luôn nằm trên các form khác kể cả khi không nhận được
Focus
Windows State Kích cỡ form khi được kích hoạt
5.1.1.2. Sự kiện trên form
Tên sự kiện Đáp ứng khi
KeyDown Khi nhấn một phím bất kỳ trên bàn phím
KeyPress Khi nhấn một phím nhưng chưa kết thúc
KeyUp Khi kết thúc thao tác nhấn một phím
Load Khi nạp form

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 53


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Tên sự kiện Đáp ứng khi


LostFocus Khi mất focus
MouseClick Khi nhấn chuột
MouseDoubleClick Nhấn đúp chuột
MouseMove Di chuyển chuột
Move Di chuyển form
Resize Khi thay đổi kích cỡ form
5.1.1.3. Một số phương thức của form
- Hiển thị một form bất kỳ:
Tên_form.Show();
- Đóng form hiện thời
This.Close();
- Đóng một form bất kỳ
Tên_form.Close();
5.1.2. Thao tác với form trong một ứng dụng
5.1.2.1. Thêm một form mới
- Nhấn phải chuột vào tên ứng dụng trong cửa sổ Solution Explorer. Nếu cửa sổ
này không hiển thị thì chọn lệnh View/Solution Explorer
- Chọn Add, Windows Form để thêm một biểu mẫu vào ứng dụng.
5.1.2.2. Xóa một form
- Nhấn phải chuột vào tên form trong cửa sổ Solution Explorer
- Chọn lệnh Delete
5.1.2.3. Thay đổi form khởi động
Ngầm định, form được tạo ra đầu tiên (form1) sẽ là form được hiển thị khi ứng
dụng kích hoạt. Tuy nhiên ta có thể chọn bất kỳ một form nào đảm nhiệm công việc
này. Thực hiện bằng cách mở file Program.cs trong cửa sổ Solution Explorer, thay
đổi form cần khởi động bằng lệnh.
5.1.3. Viết code cho các sự kiện trên form
Thao tác chung để viết code cho các sự kiện trên form hoặc trên một điều khiển
bất kỳ được thực hiện:
i. Right Click lên đối tượng cần thao tác

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 54


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

ii. Chọn Properties

iii. Chọn Events --> double click vào sự kiện cần thực hiện
Có nhiều cách để gọi cửa sổ Code. Ta có thể gọi bằng cách nhấn F7 hoặc nhấn
phải chuột vào biểu mẫu và chọn View Code. Thao tác nhắp đúp vào biểu mẫu sẽ mở
ra cửa sổ code của sự kiện Form_Load.

Ví dụ: Thiết kế form1 với tên form là Hello, tiêu đề là First Program, khi khởi
động nằm chính giữa màn hình, con trỏ có hình bàn tay khi ở trên form và khi nhấn
đúp vào form xuất hiện dòng chữ Hello Programmer.
- Bước 1: Khởi động Visual Studio
- Bước 2: Tạo ứng dụng mới lấy tên Hello
- Bước 3: Thiết lập các thuộc tính của form 1:
+ Name: hello
+ Curssor: chọn hình bàn tay Hand
+ StartPosition: Center Screen
+ Text: First Program
- Bước 4: Viết code:
+ Gọi cửa sổ code
+ Gọi sự kiện Double Click
+ Nhập dòng mã:
MessageBox.Show ("Hello!");
Đoạn code đầy đủ cho sự kiện Double Click của form sẽ được hiển thị như sau:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 55


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Kết quả khi chạy chương trình ta thấy form nằm chính giữa màn hình và được
thể hiện như trong hình bên trái. Khi nhắp đúp chuột vào một vị trí bất kỳ tại vùng
làm việc của form ta thấy dòng chữ Hello xuất hiện dưới dạng một hộp thoại như
trong hình bên phải.

5.1.4. Form MDI


Trong các ứng dụng Windows ví dụ như Word chúng ta thường thấy các cửa sổ
văn bản xuất hiện bên trong cửa sổ Word và không bao giờ vượt ra khỏi phạm vi của
cửa sổ ứng dụng này. Đấy là một minh họa của form MDI Parent gọi tắt là MDI.
Form MDI là một loại form đặc biệt thường được sử dụng làm cửa sổ chính cho
ứng dụng. Trong một ứng dụng chỉ có một cửa sổ MDI. Các cửa sổ con bên trong
MDI chỉ có thể di chuyển trong phạm vi của cửa sổ MDI chứa nó.
Khi cửa sổ con bên trong MDI được maximize thì kích thước cũng chỉ bằng
vùng làm việc của MDI. Lúc này tiêu đề của cửa sổ con được ghép với tiêu đề
của cửa sổ MDI và nếu có menu thì menu cửa sổ con sẽ thay thế menu của cửa sổ
MDI.
Khi cửa sổ con được minimize, biểu tượng của cửa sổ con nó nằm trong
cửa sổ MDI.
Form MDI được thiết lập bằng hai cách. Cách thứ nhất ta có thể set thuộc tính
IsMDIContainer của một form bất kỳ về True. Cách thứ 2 ta có thể bổ sung vào
project một form MDI bằng cách nhấn phải chuột vào project, chọn Add, New Item
và chọn MDI Parent form. Ngầm định các form MDI có nền màu xám đậm.
Sau khi đã thiết lập form MDI ta có thể chỉ định một form bất kỳ làm MDI con
bằng cách set thuộc tính MDIparent của nó là tên của form MDI vừa thành lập.
5.2. Các hộp thoại thông báo
5.2.1. MessageBox
- Công dụng: Hiển thị hộp thoại chứa thông tin chỉ dẫn đến user. Bao gồm các
phần: text, button, symbol

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 56


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

- Phương thức:
Lớp MessageBox có phương thức tĩnh Show để hiển thị dialog. Lấy giá trị
trả về để biết phản ứng của user.
Có khoảng 21 phiên bản của Show. Một số phiên bản thường sử dụng:
o MessageBox.Show (String strText)
o MessageBox.Show (String strText, String strCaption)
o MessageBox.Show (String strTex, String strCaption, MessageBoxButtons
mbb)
o MessageBox.Show (String strTex, String strCaption, MessageBoxButtons
mbb, MessageBoxIcon mbi)
o MessageBox.Show (String strTex, String strCaption, MessageBoxButtons
mbb, MessageBoxIcon mbi, MessageBoxDefaultButton mbdb)
o MessageBox.Show (String strTex, String strCaption, MessageBoxButtons
mbb, MessageBoxIcon mbi, MessageBoxDefaultButton mbdb,
MessageBoxOptions mbo)
Các button hiển thị theo message, cho phép user chọn lựa các phản ứng với
message.
- Ví dụ:
MessageBox.Show(“Bạn khỏe không?", “Câu hỏi",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
5.2.2. OpenFileDialog
- Công dụng: Sử dụng để chọn file lưu trên đĩa
- Thuộc tính và phương thức:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 57


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

- Cách thực hiện:


+ ToolBox

+ Viết code

5.2.3. SaveFileDialog
- Công dụng: Sử dụng để tạo file trên đĩa
- Cách thực hiện:
+ Sử dụng SaveFileDialog component trên Toolboz, tương tự như
OpenFileDialog!
+ Tạo thể hiện của lớp SaveFileDialog

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 58


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

5.2.4. FontDialog
- Công dụng:
+ Chức năng hiển thị hộp thoại chọn font chữ được install trong máy, trong
ứng dụng làm việc với document, đồ họa…
+ Sử dụng FontDialog
. Từ ToolBox kéo thả FontDialog vào Form: sử dụng trong lúc thiết kế
. Khai báo thể hiện FontDialog và hiển thị: viết code
- Thuộc tính và phương thức

Bổ sung chức năng “Apply” của FontDialog: khi FontDialog đang hiển thị cho
phép user kích chọn nút Apply  label thay đổi font theo.
- Cách thực hiện:
- Khai báo có hiện thị button Apply cho FontDialog

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 59


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

+ fontDialog1.ShowApply = true
+ Đăng ký trình xử lý sự kiện cho button “Apply”
. Tạo trình xử lý cho sự kiện “Apply” của FontDialog
. Đăng ký trình xử lý cho sự kiện Apply của FontDialog
5.2.5. ColorDialog
- Công dụng: Hiển thị chức năng chọn màu
- Cách thực hiện: Sử dụng theo 2 cách: kéo ColorDialog từ Toolbox thả vào
form hoặc viết code tạo đối tượng. ColorDialog sử dụng giá trị màu có kiểu Color:
ARGB, Alpha, Red, Green, Blue.
Ví dụ:

5.2.6. PrintDialog
- Công dụng: Tạo ra hộp thoại Print File.

- Cách thực hiện: - Nhắp đúp vào control


5.3. Menu
5.3.1. MenuStrip
5.3.1.1. Khái niệm
MenuStrip là khái niệm dùng để chỉ đối tượng được trình bày trên Form, đối
tượng này tổ chức các phần tử (ToolStripMenuItem) theo cấu trúc cây và trình bày
trên màn hình thành thanh menu để người sử dụng có thể lựa chọn.
5.3.1.2. Các thuộc tính
- AllowItemReorder: Thuộc tính này cho phép người sử dụng tùy chọn các
phần tử bằng bàn phím khi bấm phím Alt.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 60


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

- TextDirection: Thuộc tính này cho phép người sử dụng thay đổi hình thức
trình bày trên menu là ngang (Horizontal) hoặc dọc (Vertical90 hoặc Vertical270).
- Items: Thuộc tính này trả về danh sách các phần tử của MenuStrip.
5.3.1.3. Quy trình thực hiện
- Từ Toolbox kéo control MenuStrip thả vào Form
- Thanh MenuBar xuất hiện trên cùng của Form
- Trên màn hình Design dễ dàng tạo lập các menu Item

Đặt ký tự & trước ký tự làm phím tắt


Tạo menu item mới bằng cách nhập vào textbox
Thiết lập Shortcut cho menu item
Menu item có thể là Textbox, ToolStripMenuItem hoặc Combobox
5.3.2. ContextMenuStrip
5.3.2.1. Khái niệm
Là khái niệm dùng để chỉ đối tượng được trình bày trên Form, đối tượng này
tổ chức các phần tử theo cấu trúc cây và trình bày trên màn hình thành thanh menu
để người sử dụng có thể lựa chọn và chỉ xuất hiện khi người dùng Right Click. Thông
thường menu này xuất hiện tùy thuộc vào đối tượng trong vùng kích chuột phải.
5.3.2.2. Quy trình thực hiện
- Trong Toobox kéo ContextMenuStrip thả vào Form

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 61


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

- Kích vào ContextMenuStrip để soạn thảo các menu item

- Khai báo sử dụng Context Menu


- Mỗi control đều có property là: ContextMenuStrip
- Khai báo thuộc tính này với ContextMenuStrip
- Khi đó user kích chuột phải lên control thì sẽ hiển thị context Menu đã cài
đặt sẵn
- Khai báo trình xử lý sự kiện Click cho ContextMenu – Kích đúp vào menu
item của Context Menu để tạo – Hoặc trong cửa sổ Properties -> Event kích
đúp vào sự kiện Click.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 62


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

BÀI TẬP CHƯƠNG 5


Câu 1: Thiết kế form đăng nhập

Câu 2: Thiết kế màn hình sở thích cá nhân

Câu 3: Thiết kế màn hình đổi tiền

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 63


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Câu 4: Tạo form với định dạng như sau:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 64


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

CHƯƠNG 6: KIẾN TRÚC ADO.NET

6.1. Active Data Object - ADO.NET


Xử lý dữ liệu là nhiệm vụ phổ biến và quan trọng của nhiều chương
trình ứng dụng. Dữ liệu được truy xuất, xử lý của một chương trình ứng dụng có thể
là một tập tin văn bản, tập tin các bản ghi, hay là một nguồn dữ liệu từ CSDL nào đó.
.NET Framework cung cấp một lượng lớn các thành phần giao diện (Win Forms, Web
Forms) hỗ trợ cho việc trình bày, kết buộc (bind) dữ liệu. Cùng với đó là nền tảng xử
lý dữ liệu ADO.NET cung cấp cách thức làm việc với nhiều loại nguồn dữ liệu khác
nhau một cách linh động. Do tính chất quan trọng của việc xử lý dữ liệu trong một
ứng dụng cùng với sự phức tạp của ADO.NET, trước khi bắt tay vào thực hiện các
bài tập thực hành, chúng ta khảo sát qua một số điểm lý thuyết cơ bản.
6.1.1. Mô hình Kết nối
Trong mô hình kết nối của ADO.NET, có một connection hoạt động được duy
trì giữa đối tượng DataReader của ứng dụng và một data source (nguồn dữ liệu). Một
dòng dữ liệu (data row) được trả về từ data source mỗi khi phương thức Read của đối
tượng DataReader được thực thi. Điểm quan trọng nhất của mô hình kết nối đó là dữ
liệu được lấy từ tập dữ liệu (các record được trả về bởi một lệnh SQL nào đó) theo
kiểu từng record một cho một lần đọc, chỉ đọc (read-only), và chỉ theo một
hướng tiến (forward-only). Hình dưới đây mô tả cách sử dụng DataReader trong chế
độ kết nối.

Các bước điển hình để làm việc với đối tượng DataReader là như sau:
1. Tạo đối tượng Connection bằng cách truyền một chuỗi Connection
string cho hàm khởi dựng của nó.
2. Khởi tạo một biến chuỗi và gán cho câu lệnh SQL dựa theo dữ liệu
muốn nạp về.
3. Khởi tạo một đối tượng Command với nội dung câu lệnh SQL đã xác
định ở trên.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 65


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

4. Tạo đối tượng DataReader bằng cách thực thi phương


thức Command.ExecuteReader(). Đối tượng này sau đó sẽ được dùng để đọc kết quả
của câu truy vấn mỗi dòng một lần.
Đoạn code sau minh họa các bước trên với Data Provider SqlClient. Đoạn
code sẽ đọc danh sách họ tên các sinh viên trong một bảng SinhVien của cơ sở dữ
liệu và hiển thị lên một điều khiển ListBox. Chi tiết về các đối tượng DataReader,
Command, Connection sẽ được đề cập chi tiết sau.
using System.Data.SqlClient;
...
// (1) Tao Connection
SqlConnection cn = new SqlConnection(chuoiKetNoi);
cn.Open();
// (2) Chuoi SQL thuc hien lay danh sach ten cac sinh vien xep tang dan theo
NgaySinh
string sql = "SELECT HoTen FROM SinhVien ORDER BY NgaySinh";
// (3) Tao doi tuong Command
SqlCommand cmd = new SqlCommand(sql, conn);
DbDataReader rdr;
// (4) Tao doi tuong DataReader
rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while (rdr.Read())
listBox1.Items.Add(rdr["HoTen"]); // Fill ListBox
rdr.Close(); // Dong datareader sau khi da su dung xong
Tham số được sử dụng trong phương thức ExecuteReader xác định đối tượng
Connection sẽ được đóng sau khi DataReader được đóng.
6.1.2. Mô hình Ngắt Kết nối
Triết lý của mô hình Ngắt kết nối đó là: Dữ liệu được nạp – sử dụng một lệnh
SQL – từ nguồn dữ liệu bên ngoài vào bộ nhớ đệm tại máy client; tập kết quả được
xử lý tại máy cục bộ; mọi cập nhật sau đó sẽ được truyền từ dữ liệu trong bộ nhớ
ngược trở lại nguồn dữ liệu.
Mô hình được gọi là “ngắt kết nối” bởi vì đối tượng kết nối chỉ được mở đủ
lâu để đọc dữ liệu từ nguồn dữ liệu và tiến hành các thao tác cập nhật. Bằng cách đưa
dữ liệu về phía máy client, tài nguyên của server – chẳng hạn như thông tin dữ liệu
Connection, bộ nhớ, thời gian xử lý – sẽ được giải phóng bớt. Tuy vậy, mô hình này
cũng có nhược điểm về thời gian cần để nạp tập dữ liệu và bộ nhớ dùng để chứa dữ
liệu tại máy client.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 66


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Như hình dưới đây minh họa, các thành phần chính của mô hình ngắt kết nối
đó là DataApdapter và DataSet. DataAdapter làm nhiệm vụ như là cầu nối giữa nguồn
dữ liệu và DataSet, nạp dữ liệu vào các bảng của DataSet và đẩy các thay đối ngược
trở lại nguồn dữ liệu. Một DataSet đóng vai trò như là một cơ sở dữ liệu quan hệ nằm
trong bộ nhớ, chứa một hay nhiều DataTables, giữa các DataTable này cũng có thể
có các mối quan hệ với nhau như trong một cơ sở dữ liệu quan hệ thực. Một DataTable
chứa các dòng và các cột dữ liệu thường được lấy từ cơ sở dữ liệu nguồn.

Trong số các phương thức và thuộc tính của DataAdapter thì Fill() và Update()
là hai phương thức quan trọng nhất. Fill() chuyển một query đến cơ sở dữ liệu và lưu
tập kết quả trả về trong một DataTable nào đó; phương thức Update() thực hiện
một thao tác thêm, xóa, cập nhật dựa trên những thay đối của đối tượng DataSet.
Các lệnh cập nhật thực sự được chứa trong các thuộc tính của DataAdapter. Chi tiết
về DataAdapter sẽ được đề cập ở phần sau.
Để minh họa cách thức làm việc với DataAdapter và DataSet, đoạn code dưới
đây giới thiệu cách tạo ra một đối tượng DataTable, nạp dữ liệu từ một cơ sở dữ liệu,
và đưa nó vào một DataSet.
string sql = "SELECT MaSinhVien, HoTen, NgaySinh FROM SinhVien";
string connStr = "Data Source=MYSERVER;Initial Catalog=qlsinhvien;
User Id=k28;Password=k28;";
// (1) Tao doi tuong data adapter
SqlDataAdapter da = new SqlDataAdapter(sql, connStr);
// (2) Tao doi tuong dataset
DataSet ds = new DataSet();
// (3) Tao mot Table co ten “SinhVien” trong dataset va nap du lieu cho no
da.Fill(ds, "SinhVien");
// (4) Hien thi danh sach ten sinh vien ra list box
DataTable dt = ds.Tables["SinhVien"];
for (int i=0; i< dt.Rows.Count;i++)
{

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 67


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

DataRow row = dt.Rows[i];


listBox1.Items.Add(row["HoTen"]);
}
Bước đầu tiên là tạo ra một thể hiện của SqlDataAdapter bằng cách truyền một
câu lệnh SELECT và chuỗi kết nối cho phương thức khởi dựng của lớp này.
DataAdapter sẽ lo đến việc tạo ra đối tượng Connection cũng như việc mở, đóng
Connection khi cần thiết. Sau khi một DataSet rỗng sẽ được tạo ra, phương thức Fill()
của DataAdapter sẽ tạo ra một DataTable có tên là “SinhVien” trong DataSet và nạp
các dòng dữ liệu vào DataTable này (bằng câu lện SQL dạng SELECT của
DataAdapter). Mỗi column của DataTable sẽ tương ứng với một column trong bảng
của cơ sở dữ liệu nguồn. Dữ liệu trong bảng dữ liệu sau đó được đưa vào một
ListBox bằng cách duyệt qua danh sách các dòng của DataTable.
6.1.3. Làm việc với mô hình Kết nối trong ADO.NET
Như đã mô tả tổng quan trong phần trước, mô hình Kết nối được dựa trên việc
thiết lập một Connection đến CSDL và sau đó sử dụng các Command để thực hiện
việc thêm, xóa, sửa, hay đọc dữ liệu từ data source (nguồn dữ liệu) được kết nối. Đặc
điểm phân biệt của mô hình này đó là các Command được phát sinh, làm việc với
data source thông qua một Connection đang hoạt động – Connection này sẽ mở cho
đến khi các thao tác được hoàn tất. Cho dù là làm việc với mô hình Kết nối hay Ngắt
kết nối, bước đầu tiên trong quá trình truy xuất một data source đó là tạo ra một đối
tượng Connection để làm đường truyền giữa ứng dụng với data source.
6.2. Các thành phần cốt lõi trong ADO.NET
Kiến trúc của ADO.NET được mô tả như hình dưới, bao gồm hai thành
phần chính: thành phần truy cập nguồn dữ liệu và thành phần lưu trữ xử lý dữ liệu.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 68


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Thành phần thứ nhất:.NET Framework Data Provider được thiết kế để thực hiện
các thao tác kết nối, gửi các lệnh xử lý đến CSDL (thành phần này còn được gọi với
một tên khác là lớp kết nối – Connectectivity Layer). Trong ADO.NET, có 4 đối
tượng chính với các chức năng cơ bản như sau:
- Connection: giúp thực hiện kết nối đến các CSDL
- Command: giúp truy cập đến CSDL và thực hiện các phát biểu SQL hay thủ
tục lưu trữ sẵn (stored procedure) của CSDL
- DataReader: dùng để đọc nhanh nguồn dữ liệu, chỉ được duyệt tuần tự theo
chiều tiến của các record
- DataAdapter: dùng để chuyển dữ liệu truy vấn được cho các đối tượng lưu
trữ và xử lý (DataSet, DataTable). DataAdapter chủ yếu thực hiện các thao
tác như SELECT, INSERT, UPDATE, DELETE
Về mặt thực chất, thành phần .NET Framework Data Provider cung cấp giao
diện lập trình chung để làm việc với các nguồn dữ liệu. Mỗi nhà cung cấp 3 đặc thù
sẽ đưa ra một loại data provider riêng. Dưới đây là bảng mô tả giao diện lập trình
cùng với các lớp cơ bản của các data provider mà ADO.NET cung cấp sẵn:

Interface SQL Server Oracle Provider OLEDB Provider ODBC


Provider

IDbConnection SqlConnection OracleConnection OledbConnection OdbcConnection

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 69


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

IDbDataAdapter SqlDataAdapter OracleDataAdapter OledbDataAdapter OdbcDataAdapter

IDbCommand SqlCommand OracleCommand OledbCommand OdbcCommand

IDbDataReader SqlDataReader OracleDataReader OledbDataReader OdbcDataReader

Để sử dụng data provider nào, chúng ta phải tiến hành khái báo using
namspace tương ứng. Chẳng hạn, using System.Data.SqlClient;
Ngoài những data provider mô tả ở bảng trên, chúng ta có thể reference đến
các data provider khác không được tích hợp sẵn bởi ADO.NET trong Visual Studio
.NET, chẳng hạn như data provider dùng cho MySQL, Postgre, …
Thành phần thứ hai trong kiến trúc ADO.NET – DataSet – được xem
như là container dùng để lưu trữ đối tượng liên quan đến dữ liệu như DataTable,
DataRelation, DataView. Thành phần này còn được gọi là lớp không kết nối
(disconected layer). DataSet như là một CSDL thu nhỏ tại máy client, có thể chứa
các đối tượng table, view, constaint, ralationship giữa các table, … Tất cả dữ liệu từ
nguồn dữ liệu thực sẽ được nạp vào DataSet dưới dạng các DataTable, đó là một
snapshot của nguồn dữ liệu thực. Khối dữ liệu này sẽ được chỉnh sửa độc lập, sau đó
nếu cần sẽ được cập nhật trở lại nguồn dữ liệu thực. Theo nguyên tắc này, chúng
ta không cần duy trì kết nối liên tục một cách không cần thiết với nguồn dữ liệu
thực trong suốt quá trình thao tác với nó.
6.3. Đối tượng Connection
Có nhiều lớp Connection trong ADO.NET – mỗi lớp tương ứng với một Data
Provider–bao gồm SqlConnection, OracleConnection, OleDbConnection,
OdbcConnection.
Mặc dù mỗi lớp có thể gồm những đặc tính riêng, nhưng các lớp này đều phải
implement interface IDbConnection. Bảng dưới đây tóm tắt các thành phần được định
nghĩa bởi interface này.
Loại Tên Mô tả
Property ConnectionString Get/Sets chuỗi kết nối đến data source.
Property ConnectionTimeout Khoảng thời gian tối đa tính bằng giây để chờ thực hiện việc kết
nối đến Data Source
Property Database Tên CSDL ứng với Connection hiện tại
Property State Trạng thái hiện tại của Connection. Trả về một giá trị kiểu liệt kê
(enumeration): Broken, Closed, Connecting, Executing, Fetching
hoặc Open
Method Open Mở một Connection. Roll back mọi thao tác đang làm dở.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 70


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Close Đóng Connection- trả Connection cho Connection Pool nếu như
có sử dụng Connection Pool
Method Begin Transaction Khởi tạo một database transaction
Method Change Database Thay đổi CSDL hiệnt ại cho Connection đang mở
Method Create Command Tạo ra một đối tượng Command ứng với Connection

6.3.1. Connection string


Thuộc tính ConnectionString xác định data source và các thông tin cần thiết
để truy xuất data source, chẳng hạn như User ID và Password, … Ngoài những thông
tin cơ bản này, Connection string còn có thể chứa các giá trị cho các trường dữ liệu
đặc trưng cho data provider. Ví dụ, Connection string cho Ms Sql Server có thể chứa
các giá trị để quy định Connection Timeout và Packet Size.
Dưới đây là các ví dụ về cách thành lập chuỗi kết nối cho các data provider
thường gặp. Danh sách đầy đủ về cách thành lập các chuỗi kết nối được cho ở Error!
Reference source not found..
- SqlConnection sử dụng cơ chế xác thực kiểu SQL Server:
“server=(1);database=(2);uid=(3);pwd=(4)” hoặc
“Data Source=(1);Initial Catalog=(2);User ID=(3);Password=(4)”

- SqlConnection sử dụng cơ chế xác thực kiểu Windows:


“Server=(1);Database=(2);Trusted_Connection=yes”
Ở đây, (1) là tên/máy chủ chứa CSDL, (2) là tên CSDL, (3) là tên đăng nhập, (4) là mật
khẩu tương ứng.
Ví dụ:
“server=192.168.0.1;database=qlnhanvien;uid=k28;pwd=spider”
hoặc
“Server=192.168.0.1;Database=qlnhanvien;Trusted_Connection=yes”
- OleDbConnection sử dụng để kết nối CSDL Access phiên bản trước 2003:

“Provider=Microsoft.Jet.OLEDB.4.0;DataSource= ”
Ví dụ:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 71


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

o string stConnection =
string.Format(“Provider=Microsoft.Jet.OLEDB.4.0;DataSource={0
}”,
@”c:\program files\qlnhanvien.mdb”);

o Sử dụng trong ứng dụng Internet:


string stConnection =
string.Format(“Provider=Microsoft.Jet.OLEDB.4.0;DataSource={0
}”,
Server.MapPath(“/data/qlnhanvien.mdb”);

- ODBC: “DSN=①” với ① là Data Source Name (DSN), ví dụ “DSN=qlnhanvien”

Các Connection string được dùng để tạo ra đối tượng Connection. Cách
thực hiện thông thường là truyền chuỗi này cho hàm khởi dựng như ví dụ dưới đây:
string stConnection =
"Data Source=192.168.0.1;” +
“Initial Catalog=films;” +
“User Id=k28;”+
“Password=spider";
SqlConnection cn = new SqlConnection(stConnection);
cn.Open(); //Open connection
6.3.2. Connection Pooling
Tạo một Connection là một quá trình tốn nhiều thời gian – trong một số trường
hợp, việc này thậm chí còn tốn thời gian hơn việc thực thi các Command. Để loại bỏ
điều này, ADO.NET cung cấp một khái niệm gọi là connection pool. Connection pool
quản lý các Connection có trùng Connection string để tối ưu hóa số lần thiết lập, hợp
lệ hóa thông tin kết nối.
Các quy tắc quy định connection pool cần biết:
- Cơ chế Connection pooling được kích hoạt theo mặc định. Cơ chế này được
tắt bằng cách thêm vào Connection string “Pooling=false” đối với
SqlConnection hoặc “OLE DB Services=-4” đối với OleDbConnection.
- Mỗi connection pool được ứng với một connection string duy nhất. Khi có
một Connection được yêu cầu, pool handler (bộ quản lý pool) sẽ so sánh connection
string với những connection string trong các pools đang tồn tại. Nếu có một
Connection trùng khớp thì Connection tương ứng sẽ được xác định trong pool.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 72


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

- Nếu tất cả các connection trong pool đang được sử dụng khi lại có yêu cầu
về connection thì yêu cầu đó sẽ được xếp vào hàng đợi cho đến khi có một
connection rảnh. Các connection sẽ được giải phóng khi phương thức Close hay
Dispose của đối tượng connection được gọi.
- Connection pool được đóng khi tất cả các connection trong nó được giải
phóng và hết thời gian (time out).
Đối với SQL Server, bạn có thể điều khiển hành vi của conneciton pooling
bằng cách gộp các cặp key-value vào connection string. Các key này có thể được sử
dụng để thiết lập số lượng nhỏ nhất và lớn nhất các connection trong pool cũng
như xác định xem một connection có cần phải reset khi nó được lấy từ pool ra hay
không. Một key đặc biệt chú ý đó là key có tên Lifetime, xác định thời gian mà
connection có thể tồn tại trước khi nó bị hủy bỏ. Giá trị này được kiểm tra khi
một connection được trả về cho pool. Nếu connection đã được mở trước đó, và
lâu hơn giá trị Lifetime thì nó sẽ bị hủy.
Đoạn code dưới đây minh họa các dùng các key này cho SqlClient:
string stConnection =
"Server=192.168.0.1;” +
“Trusted_Connection=yes;” +
“database=qlnhanvien;" +
"connection reset=false;" +
"connection Lifetime=60;" + // Seconds
"min pool size=1;" +
"max pool size=50"; // Default=100
SqlConnection cn = new SqlConnection(cnString);
6.4. Đối tượng Command
Sau khi một đối tượng connection được tạo ra, bước tiếp theo trong quá trình
truy xuất CSDL – đối với mô hình Kết nối – đó là tạo ra một đối tượng Command
để gửi một query (select) hay một action command (thêm, xóa, sửa) đến data source.
Có nhiều loại lớp Command ứng với các data provider; các lớp này đều
implement interface IDbCommand.
6.4.1. Tạo đối tượng Command
Bạn có thể dùng một trong nhiều hàm khởi dựng để tạo đối tượng Command
một cách trực tiếp hoặc sử dụng cách tiếp cận ProviderFactory.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 73


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Đoạn code dưới đây minh họa các tạo ra một đối tượng Command và thiết lập
các thuộc tính của nó.
SqlConnection conn = new SqlConnection(connstr);
conn.open();
string sql =
"INSERT INTO SinhVien (MaSinhVien, HoTen) VALUES (@pMaSinhVien,
@pHoTen)";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.commandText = sql;
cmd.Parameters.AddWithValue ("@pMaSinhVien", 12);
cmd.Parameters.AddWithValue ("@pHoTen", "tnv spider");
Trong trường hợp ứng dụng có thể phải sử dụng nhiều data provider, bạn nên
sử dụng cách tiếp cận provider factory. Factory được tạo ra bằng cách truyền chuỗi
data provider cho hàm khởi dựng của nó. Tiếp đến, phương thức CreateCommand
được gọi để trả về một đối tượng command.
string provider = "System.Data.SqlClient";
DBProviderFactory factory = DbProviderFactories.GetFactory(provider);
DbCommand cmd = factory.CreateCommand(); // DbCommand là một lớp
trừu tượng
cmd.CommandText = sql; // sql là một chuỗi query hay command
cmd.Connection = conn; // conn là một Connection
6.4.2. Thực thi một Command
Lệnh SQL được gán trong thuộc tính CommandText của đối tượng Command
sẽ được thực thi bằng một trong các phương thức được chỉ ra ở bảng dưới đây:

Phương thức Mô tả

ExecuteNonQuery Thực thi truy vấn hành động (action query) và trả về số lượng dòng
dữ liệu bị ảnh hưởng bởi truy vấn đó:
cmd.CommandText = "DELETE SinhVien WHERE
MaSinhVien=12";
int soLuong = cmd.ExecuteNonQuery();

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 74


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

ExecuteReader Thực thi một query và trả về đối tượng DataReader để có thể truy cập
tập kết quả của query đó. Phương thức này nhận một tham số tùy chọn
kiểu CommandBehavior để có thể tăng hiệu năng thực thi
query.
cmd.CommandText = "SELECT * FROM SinhVien” + “WHERE
YEAR(NgaySinh) > 1981”;
SqlDataReader rdr= cmd.ExecuteReader();

ExecuteScalar Thực thi một query và trả về giá trị của cột đầu tiên trong dòng đầu
tiên của tập kết quả.
cmd.CommandText="SELECT COUNT(MaSinhVien) FROM SinhVien";
int soSinhVien= (int)cmd.ExecuteScalar();

ExecuteXmlReader Chỉ có cho data provider SQL Server. Trả về một đối tượng
XmlReader dùng để truy xuất tập dữ liệu. Tham khảo thông tin về
XmlReader trong MSDN

ExecuteReader là phương thức quan trọng nhất trong các phương thức kể trên.
Phương thức này trả về một đối tượng DataReader giúp truy xuất đến các dòng dữ
liệu trả về bởi query. Xem ví dụ dưới đây:
dr = cmd.ExecuteReader(sql, ①);

Ở đây, ① là một giá trị kiểu CommandBehavior để chỉ định behavior (hành vi)
thực thi của query. Một số data providers sử dụng ① để tối ưu quá trình thực thi
query. Danh sách các giá trị và tác dụng của tham số ① được mô tả chi tiết như dưới
đây:
+ SingleRow. Chỉ định rằng query chỉ trả về 1 dòng dữ liệu. Behavior mặc
định là trả về nhiều tập kết quả.
+ SingleResult. Query trả về một giá trị tuyến tính đơn nhất (single scalar
value).
+ KeyInfo. Trả về thông tin về column và primary key. Behavior này được sử
dụng với phương thức GetSchema của DataReader để lấy thông tin về các column
trong lược đồ (schema).
+ SchemaOnly. Dùng để lấy về tên của các cột trong tập dữ liệu trả về:
Ví dụ:
dr = cmd.ExecuteReader(CommandBehavior.SchemaOnly);

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 75


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

string col1 = dr.GetName(0); // tên cột đầu tiên


+ SequentialAccess. Cho phép dữ liệu trong dòng trả về có thể được truy xuất
tuần tự theo column. Behavior này được dùng cho các trường dữ liệu BLOB hay
TEXT.
+ CloseConnection. Đóng connection khi DataReader được đóng.
6.4.3. Thực thi Stored Procedure (thủ tục lưu trữ sẵn) với đối tượng Command
Một stored procedure là một đoạn code SQL được lưu sẵn trong CSDL và có
thể được thực thi như là một script. ADO.NET hỗ trợ việc thực thi các stored
procedure cho các data provider OleDb , SqlClient, ODBC, và OracleClient.
Các bước để thực thi một stored procedure:
- Thiết lập thuộc tính SqlCommand.CommandText thành tên của procedure;
- Thiết lập thuộc tính CommandType là CommandType.StoredProcedure;
- Thiết lập các Parameter (nếu có) cho procedure
- Thực thi phương thức ExecuteNonQuery.
Thủ tục dưới đây cho phép các mẫu tin lấy về từ bảng SinhVien được phân
thành từng nhóm các trang, mỗi trang 10 record. Đầu vào của của procedure là
@pTrang (số hiệu trang cần lấy); đầu ra của procedure là số trang tổng cộng của
tập dữ liệu. Đoạn code minh họa phía dưới thực hiện việc thiết lập để lấy về trang
dữ liệu đầu tiên.
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "spListSinhVien"; // tên procedure
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(“@pTrang", SqlDbType.Int);
cmd.Parameters.Add(“@pTongSoTrang", SqlDbType.Int);
cmd.Parameters[0].Direction= ParameterDirection.Input;
cmd.Parameters[0].Value= 1; // thiết lập để lấy về trang đầu tiên
cmd.Parameters[1].Direction=ParameterDirection.Output;
cmd.CommandTimeout=10; // Cho command tối đa 10s để thực thi
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
// xử lý tập dữ liệu ở đây
}
dr.Close(); // DataReader phải được đóng trước khi đọc tham số đầu ra
int tongSoTrang = cmd.Parameters[1].Value;

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 76


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Ví dụ này sử dụng data provider SqlClient. Có thể chỉnh sửa một phần nhỏ thì
nó cũng có thể hoạt động với OleDb. Điểm khác biệt mấu chốt giữa SqlClient và
OleDb đó là cách quản lý các parameter. SqlClient yêu cầu tên parameter phải đúng
với tên parameter của stored procedure; trong khi đó OleDb lại truyền các parameter
cho stored procedure dựa vào vị trí, vì vậy tên parameter là không quan trọng. Nếu
procedure trả về giá trị kết quả, OleDb phải thiết kế để parameter đầu tiên trong
danh sách làm nhiệm vụ này. Với SqlClient, chúng ta chỉ cần thêm một parameter
với một tên nào đó và xác định hướng trả về (direction) của parameter này là Return
Value.
Phần code của stored procedure là như sau:
CREATE PROCEDURE spListSinhVien
@pTrang int,
@pTongSoTrang int output
AS
/*
Thủ tục trả về một tập kết quả gồm các SinhVien xếp theo HoTen. Tập kết
quả được phân thành các trang, mỗi trang 10 SinhVien.
*/
SET NOCOUNT ON
SELECT @pSoTrang = CEILING(COUNT(*)/10) FROM SinhVien
if @pTrang = 1 or @pTrang <1
begin
SELECT TOP MaSinhVien, HoTen FROM SinhVien ORDER BY HoTen
set @pTrang = 1
return 0
end
if @pTrang > @pTongSoTrang
begin
SET @pTrang = @pTongSoTrang
declare @RowCount int
set @RowCount = (@pTrang * 10)
exec (
'SELECT *
FROM (

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 77


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

SELECT TOP 10 a.*


FROM (
SELECT TOP ' + @RowCount + ' *
FROM SinhVien
ORDER BY HoTen
) a
ORDER BY HoTen desc
) b
ORDER BY HoTen'
)
return 0
end
6.4.4. Sử dụng Parameter trong các Command không phải là Stored Procedures
Trong các query được thành lập trực tiếp (chứ không phải là stored procedure
như ở trên), chúng ta cũng có thể sử dụng các Parameter. Ví dụ dưới đây minh họa
cách thức bổ sung một record vào bảng SinhVien:
string sql =
"INSERT INTO SinhVien (MaSinhVien, HoTen) VALUES (@pMaSinhVien, @pHoTen)";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.commandText = sql;
cmd.Parameters.AddWithValue("@pMaSinhVien", 12);
cmd.Parameters.AddWithValue("@pHoTen", "tnv spider");
Một cách khác để thực hiện việc bổ sung record như trên là sử dụng phép nối
chuỗi4 như thế này:
int iMaSinhVien = 12;
string stHoTen = "tnv spider";
sql = string.Format(“INSERT INTO SinhVien (MaSinhVien, HoTen)
VALUES ({0}, ‘{1}’)”,
iMaSinhVien, stHoTen);
SqlCommand cmd = new SqlCommand(sql, conn);
6.5. Đối tượng DataReader
Như đã thấy trong các ví dụ trước, một DataReader cho phép lấy các dòng và
cột dữ liệu của dữ liệu trả về khi thực thi một query. Việc truy xuất dòng

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 78


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

được định nghĩa bởi interface IDataRecord. Dưới đây là các member quan trọng
của interface này.
6.5.1. Truy xuất các dòng dữ liệu với DataReader
DataReader lấy về từng dòng đơn (single row) từ một tập dữ liệu trả về mỗi
khi phương thức Read của nó được thực thi. Nếu không có dòng dữ liệu nào thì
phương thức này trả về giá trị false. DataReader phải được đóng sau khi các thao tác
xử lý các dòng được hoàn tất để giải phóng tài nguyên hệ thống. Bạn có thể sử dụng
thuộc tính DataReader.IsClosed để biết được DataReader đã được đóng hay chưa.
Mặc dù DataReader là ứng với một Command đơn, nhưng Command này lại
có thể chứa nhiều query trong đó, do đó có thể trả về nhiều tập dữ liệu kết quả. Đoạn
code dưới đây minh họa cách xử lý các dòng dữ liệu trả về bởi 2 query trong một
Command.
string q1 = "SELECT * FROM SinhVien WHERE YEAR(NgaySinh) < 1981";
string q2 = "SELECT * FROM SinhVien WHERE YEAR(NgaySinh) > 1990";
cmd.CommandText = q1 + ";" + q2; // hai query được ngăn cách nhau bởi dấu ;
DbDataReader rdr = cmd.ExecuteReader();
bool readNext = true;
while (readNext)
{
while (rdr.Read())
MessageBox.Show(rdr.GetString(1));
readNext = rdr.NextResult(); // kiem tra con tap du lieu nao nua khong
}
rdr.Close();
conn.Close();
DataReader không có thuộc tính hay phương thức nào cho biết số lượng dòng
dữ liệu trả về trong tập dữ liệu của nó (do đặc tính forward-only của DataReader), tuy
nhiên, chúng ta có thể sử dụng thuộc tính HasRows (kiểu Boolean) của DataReader
để xác định xem nó có 1 hay nhiều dòng để đọc hay không.
6.5.2. Truy xuất giá trị của column
Có nhiều cách để truy xuất dữ liệu chứa trong các columns của dòng
hiện tại của DataReader:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 79


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

- Truy xuất như là một array dùng số thứ tự column (bắt đầu từ
0) hoặc dùng tên column
- Sử dụng phương thức GetValue bằng cách truyền cho phương thức
này số thứ tự của column
- Sử dụng một trong các phương thức định kiểu GetXXX, bao
gồm GetString, GetInt32, GetDateTime, GetDouble, …
Đoạn code dưới đây minh họa các thức truy xuất giá trị dữ liệu của các column.
cmd.CommandText =
"SELECT MaSinhVien, Hoten, GioiTinh, NgaySinh FROM SinhVien ” +
“WHERE YEAR(NgaySinh) = 1981";
dr = cmd.ExecuteReader();
dr.Read();
// Các cách để lấy dữ liệu kiểu string ở cột thứ 2 (HoTen)
string stHoTen;
stHoTen = dr.GetString(1);
stHoTen = (string)dr.GetSqlString(1); // SqlClient provider
stHoTen = (string)dr.GetValue(1);
stHoTen = (string)dr["HoTen"];
stHoTen = (string)dr[1];
// Lấy dữ liệu kiểu DateTime ở cột thứ 4 (NgaySinh) có kiểm tra giá trị NULL
if (!dr.IsDbNull(3))
DateTime dtNgaySinh = dr.GetDateTime(3);
Phương thức GetString có điểm thuận lợi trong việc ánh xạ nội dung dữ
liệu từ CSDL sang kiểu dữ liệu của .NET. Các cách tiếp cận khác đều trả về các kiểu
đối tượng có yêu cầu phép chuyển kiểu. Vì lý do này, bạn nên sử dụng các phương
thức GetXXX cho các kiểu dữ liệu xác định. Cũng lưu ý rằng, phương thức GetString
không yêu cầu phép chuyển kiểu, nhưng bản thân nó không thực hiện bất cứ phép
chuyển đổi nào; chính vì thế, nếu dữ liệu là không đúng như kiểu dữ liệu trông đợi sẽ
có Exception được trả ra.
Nhiều ứng dụng phụ thuộc vào tầng xử lý dữ liệu để cung cấp
DataReader. Với những trường hợp như thế, ứng dụng có thể sử dụng metadata (siêu
dữ liệu) để xác định tên column, kiểu dữ liệu của column, và các thông tin khác về
column. Đoạn code sau đây minh họa việc in ra danh sách các tên và kiểu dữ
liệu của các column mà đối tượng DataReader đang quản lý:
// In ra danh sách các tên column của một đối tượng DataReader có tên dr
for (int i = 0; i < dr.FieldCount; i++)

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 80


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Console.WriteLine(“Column {0} co kieu du lieu {1}”,


dr.GetName(i), dr.GetDataTypeName(i)); // Column name
Có một cách khác toàn diện hơn để quản lý toàn bộ thông tin về lược đồ
(schema) của tập dữ liệu kết quả trả về, đó là sử dụng phương thức GetSchemaTable.
Phương thức này trả về một đối tượng DataTable mà mỗi dòng trong DataTable này
sẽ biểu diễn một column trong tập dữ liệu kết quả. Đoạn code dưới đây minh họa
cách truy xuất tất cả các thông tin về các column của một tập dữ liệu trả về.
DataTable schemaTable = dr.GetSchemaTable();
int stt = 0;
foreach (DataRow r in schemaTable.Rows)
{
foreach (DataColumn c in schemaTable.Columns)
{
Console.WriteLine(stt.ToString() + " " + c.ColumnName + ": " + r[c]);
stt++;
}
}
Kết quả hiển thị:
0 ColumnName: movie_ID
1 ColumnOrdinal: 0
… //không liệt kê
12 DataType: System.Int32
… //không liệt kê
6.6. Làm việc với mô hình Ngắt kết nối: DataSet và DataTable
Mô hình Ngắt Kết nối của ADO.NET dựa trên cơ sở sử dụng đối tượng
DataSet như là một vùng nhớ đệm. Một đối tượng DataAdapter làm nhiệm vụ trung
gian giữa DataSet và data source (nguồn dữ liệu) để nạp dữ liệu vào vùng nhớ đệm.
Sau khi DataAdapter hoàn thành nhiệm vụ nạp dữ liệu, nó sẽ trả đối tượng Connection
về pool, vì thế nó ngắt kết nối khỏi nguồn dữ liệu.
6.6.1. Lớp DataSet
DataSet đóng vai trò của một CSDL in-memory (CSDL nằm trong bộ nhớ).
Thuộc tính Tables của DataSet là một tập hợp các DataTable chứa dữ liệu và lược đồ

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 81


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

dữ liệu (data schema) mô tả dữ liệu trong DataTable. Thuộc tính Relations chứa tập
hợp các đối tượng DataRelation xác định cách thức liên kết các đối tượng
DataTable của DataSet. Lớp DataSet cũng hỗ trợ việc sao chép, trộn, và xóa DataSet
thông qua các phương thức tương ứng là Copy, Merge, và Clear.
DataSet và DataTable là phần lõi của ADO.NET và chúng không là đặc trưng
của một data provider nào (giống như ở các lớp Connection, DataReader,
DataAdapter). Một ứng dụng có thể định nghĩa và nạp dữ liệu từ nguồn bất kỳ (chứ
không nhất thiết là từ một CSDL) vào DataSet.
Bên cạnh các DataTable và các DataRelation, một DataSet còn có thể
chứa các thông tin tùy biến khác được định nghĩa bởi ứng dụng. Hình dưới đây mô
tả cả lớp chính trong DataSet. Trong số các thuộc tính này, chú ý thuộc tính
PropertyCollection; đó là các thuộc tính được lưu trữ dưới dạng một hash table (bảng
băm), thường chứa một giá trị time stamp hay các thông tin đặc tả như các yêu cầu
hợp lệ hóa (validation requirements) cho column trong các DataTable trong DataSet.

3.6.1.1 DataTable
Thuộc tính DataSet.Tables chứa các đối tượng DataTable. Mỗi đối tượng trong
tập hợp này có thể được truy xuất bằng chỉ số hoặc bằng tên.
Các DataTable trong tập hợp DataSet.DataTables mô phỏng các Table trong
CSDL quan hệ (các row, column, …). Các thuộc tính quan trọng nhất của lớp
DataTable là Columns và Rows định nghĩa cấu trúc và nội dung bảng dữ liệu.
3.6.1.2. DataColumn

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 82


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

Thuộc tính DataTable.Columns chứa một tập các đối tượng DataColumn biểu
diễn các trường dữ liệu trong DataTable. Bảng dưới đây tóm tắt các thuộc tính quan
trọng của lớp DataColumn.

Phương thức Mô tả

ColumnName Tên column

DataType Kiểu của dữ liệu chứa trong column này


Ví dụ: col1.DataType = System.Type.GetType("System.String")

MaxLength Độ dài tối đa của một text column. -1 nếu không xác định độ dài tối đa

ReadOnly Cho biết giá trị của column có được chỉnh sửa hay không

AllowDBNull Giá trị Boolean cho biết column này có được chứa giá trị NULL hay
không

Unique Giá trị Boolean cho biết column này có được chứa các giá trị trùng nhau
hay không

Expression Biểu thức định nghĩa cách tính giá trị của một column
Ví dụ: colTax.Expression = "colSales * .085";

Caption Tiêu đề hiển thị trong thành phần điều khiển giao diện đồ họa

DataTable Tên của đối tượng DataTable chứa column này

Các column của DataTable được tạo ra một cách tự động khi table được nạp
dữ liệu từ kết quả của một database query hoặc từ kết quả đọc được ở một file XML.
Tuy nhiên, chúng ta cũng có thể viết code để tạo động các column. Đoạn code dưới
đây sẽ tạo ra một đối tượng DataTable, sau đó tạo thêm các đối tượng DataColumn,
gán giá trị cho các thuộc tính của column, và bổ sung các DataColumn này vào
DataTable.
DataTable tb = new DataTable("DonHang");
DataColumn dCol = new DataColumn("MaSo", Type.GetType("System.Int16"));
dCol.Unique = true; // Dữ liệu của các dòng ở column này không được trùng
nhau
dCol.AllowDBNull = false;

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 83


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

tb.Columns.Add(dCol);
dCol = new DataColumn("DonGia", Type.GetType("System.Decimal"));
tb.Columns.Add(dCol);
dCol = new DataColumn("SoLuong",Type.GetType("System.Int16"));
tb.Columns.Add(dCol);
dCol= new DataColumn("ThanhTien",Type.GetType("System.Decimal"));
dCol.Expression= "SoLuong*DonGia";
tb.Columns.Add(dCol);
// Liệt kê danh sách các Column trong DataTable
foreach (DataColumn dc in tb.Columns)
{
Console.WriteLine(dc.ColumnName);
Console.WriteLine(dc.DataType.ToString());
}
Để ý rằng column MaSo được định nghĩa để chứa các giá trị duy nhất. Ràng
buộc này giúp cho column này có thể được dùng như là trường khóa để thiết lập
relationship kiểu parent-child với một bảng khác trong DataSet. Để mô tả, khóa
phải là duy nhất – như trong trường hợp này – hoặc được định nghĩa như là một
primary key của bảng. Ví dụ dưới đây mô tả cách xác định primary key của bảng:
DataColumn[] col = {tb.Columns["MaSo"]};
tb.PrimaryKey = col;
Nếu một primary key chứa nhiều hơn 1 column – chẳng hạn như HoDem và
Ten – bạn có thể tạo ra một ràng buộc unique constraint trên các như ví dụ dưới đây:
DataColumn[] cols = {tb.Columns["HoDem"], tb.Columns["Ten"]};
tb.Constraints.Add(new UniqueConstraint("keyHoVaTen", cols));
Chúng ta sẽ xem xét cách thức tạo relationship cho các bảng và trộn dữ liệu ở phần tiếp theo.
3.6.1.3. DataRows
Dữ liệu được đưa vào table bằng cách tạo mới một đối tượng DataRow, gán
giá trị cho các column của nó, sau đó bổ sung đối tượng DataRow này vào tập hợp
Rows gồm các DataRow của table.
DataRow row;
row = tb.NewRow(); // Tạo mới DataRow
row["DonGia"] = 22.95;
row["SoLuong"] = 2;
row["MaSo"] = 12001;

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 84


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

tb.Rows.Add(row); // Bổ sung row vào tập Rows


Console.WriteLine(tb.Rows[0]["ThanhTien"].ToString()); // 45.90
Một DataTable có các phương thức cho phép nó có thể commit hay roll back
các thay đổi được tạo ra đối với table tương ứng. Để thực hiện được điều này, nó phải
nắm giữ trạng thái của mỗi dòng dữ liệu bằng thuộc tính DataRow.RowState. Thuộc
tính này được thiết lập bằng một trong 5 giá trị kiểu enumeration DataRowState
sau: Added, Deleted, Detached, Modifed, hoặc Unchanged. Xem xét ví dụ sau:
tb.Rows.Add(row); // Added
tb.AcceptChanges(); // ...Commit changes
Console.Write(row.RowState); // Unchanged
tb.Rows[0].Delete(); // Deleted
// Undo deletion
tb.RejectChanges(); // ...Roll back
Console.Write(tb.Rows[0].RowState); // Unchanged
DataRow myRow;
MyRow = tb.NewRow(); // Detached
Hai phương thức AcceptChanges và RejectChanges của DataTable là
tương đương với các thao tác commit và rollback trong một CSDL. Các phương thức
này sẽ cập nhất mọi thay đổi xảy ra kể từ khi table được nạp, hoặc từ khi phương thức
AcceptChanges được triệu gọi trước đó. Ở ví dụ trên, chúng ta có thể khôi phục lại
dòng bị xóa do thao tác xóa là chưa được commit trước khi phương thức
RejectChanges được gọi. Điều đáng lưu ý nhất đó là, những thay đổi được thực hiện
là ở trên table chứ không phải là ở data source.
ADO.NET quản lý 2 giá trị - ứng với 2 phiên bản hiện tại và nguyên gốc - cho
mỗi column trong một dòng dữ liệu. Khi phương thức RejectChanges được gọi,
các giá trị hiện tại sẽ được đặt khôi phục lại từ giá trị nguyên gốc. Điều ngược lại
được thực hiện khi gọi phương thức AcceptChanges. Hai tập giá trị này có thể
được truy xuất đồng thời thông qua các giá trị liệt kê DataRowVersion là: Current
và Original:
DataRow r = tb.Rows[0];
r["DonGia"]= 14.95;
r.AcceptChanges();
r["DonGia"]= 16.95;
Console.WriteLine("Current: {0} Original: {1} ",
r["Price", DataRowVersion.Current],

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 85


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

r["Price", DataRowVersion.Original]);
Kết quả in ra:
Current: 16.95 Original: 14.95
3.6.1.4. DataView.
DataView đóng vai trò như tầng hiển thị dữ liệu lưu trữ trong DataTable. Nó
cho phép người sử dụng sắp xếp, lọc và tìm kiếm dữ liệu.
//Giả sử đã có 1 dataset có tên là ds chứa dữ liệu của bảng DonHang
DataView dv = new DataView(ds.Tables["DonHang”];
// Lọc ra tất cả các hàng có giá từ 10 đến 100
dv.RowFilter = "soluong>=10 and soluong<=100";
//Sắp xếp tăng dần theo số lượng nếu số lượng bằng nhau thì sắp xếp giảm dần
thêm đơn
giá
dv.Sort = "soluong, dongia DESC";
6.6.2. Nạp dữ liệu vào DataSet
Chúng ta đã biết cách thành lập một DataTable và xử lý dữ liệu theo kiểu từng
dòng một. Phần này sẽ trình bày phương pháp để dữ liệu và lược đồ dữ liệu được nạp
tự động từ CSDL quan hệ vào các table trong DataSet.
3.6.2.1. Dùng DataReader để nạp dữ liệu vào DataSet
Đối tượng DataReader có thể được sử dụng để liên hợp đối tượng DataSet hay
DataTable trong việc nạp các dòng dữ liệu kết quả (của query trong DataReader).
cmd.CommandText = "SELECT * FROM nhanvien";
DBDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
DataTable dt = new DataTable("nhanvien");
dt.Load(rdr); // Nạp dữ liệu và lược đồ vào table
Console.WriteLine(rdr.IsClosed); // True
Đối tượng DataReader được tự động đóng sau khi tất cả các dòng dữ liệu được
nạp vào table. Do đã sử dụng tham số CommandBehavior.CloseConnection trong
phương thức ExecuteReader nên connection được đóng sau khi DataReader được
đóng.
Nếu table đã có dữ liệu, phương thức Load sẽ trộn dữ liệu mới với các dòng
dữ liệu đang có trong nó. Việc trộn này xảy ra chỉ khi các dòng dữ liệu có chung
primary key. Nếu không có primary key được định nghĩa, các dòng dữ liệu sẽ được
nối vào sau tập dữ liệu hiện tại. Chúng ta có thể sử dụng phương thức nạp chồng khác
của phương thức Load để quy định cách thức làm việc. Phương thức Load với
tham số kiểu enumeration LoadOption gồm 1 trong 3 giá trị OverwriteRow,

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 86


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

PreserveCurrentValues, hoặc UpdateCurrentValues tương ứng với tùy chọn ghi đè


nguyên dòng, giữ lại các giá trị hiện tại, hoặc cập nhật các giá trị hiện tại. Đoạn code
dưới đây minh họa cách trộn dữ liệu vào các dòng hiện tại theo kiểu ghi đè các giá trị
hiện tại:
cmd.CommandText = "SELECT * FROM nhanvien WHERE diachi=’a’";
DBDataReader rdr = cmd.ExecuteReader();
DataTable dt = new DataTable("nhanvien");
dt.Load(rdr);
Console.Write(dt.Rows[0]["HoTen"]); // giả sử giá trị nhận được là “tnv
spider”
// Gán khóa chính
DataColumn[] col = new DataColumn[1];
col[0] = dt.Columns["Manv"];
dt.PrimaryKey = col;
DataRow r = dt.Rows[0]; // lấy dòng đầu tiên
r["HoTen"] = "ten moi"; // thay đổi giá trị của cột HoTen
// Do reader đã bị đóng sau khi nạp vào data table nên phải giờ phải fill lại
rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
// Trộn dữ liệu với các dòng hiện tại. Ghi đè các giá trị hiện tại
dt.Load(rdr, LoadOption.UpdateCurrentValues);
// Giá trị cập nhật đã bị ghi đè!!!
Console.Write(dt.Rows[0]["HoTen"]); // “tnv spider”
3.6.2.2. Nạp dữ liệu vào DataSet bằng DataAdapter
Đối tượng DataAdapter có thể được dùng để nạp một table hiện có vào một
table khác, hoặc tạo mới và nạp dữ liệu cho table từ kết quả của một query. Bước đầu
tiên là tạo ra một đối tượng DataAdapter tương ứng với data provider cụ thể. Dưới
đây là các ví dụ để tạo ra đối tượng DataAdapter:
(1) Tạo từ Connection string và câu truy vấn SELECT:
String sql = "SELECT * FROM nhanvien";
SqlDataAdapter da = new SqlDataAdapter(sql, connStr);
(2) Tạo từ đối tượng Connection và câu truy vấn SELECT:
SqlConnection conn = new SqlConnection(connStr);
SqlDataAdapter da = new SqlDataAdapter(sql, conn);

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 87


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

(3) Gán đối tượng Command cho thuộc tính SelectCommand


SqlDataAdapter da = new SqlDataAdapter();
SqlConnection conn = new SqlConnection(connStr);
da.SelectCommand = new SqlCommand(sql, conn);
Sau khi đối tượng DataAdapter đã được tạo ra, phương thức Fill của nó được
thực thi để nạp dữ liệu vào table (đang tồn tại hoặc tạo mới). Ở ví dụ dưới đây, một
table mới được tạo ra với tên mặc định là “Table”:
DataSet ds = new DataSet();
// Tạo ra một DataTable, nạp dữ liệu vào DataTable, và
đưa DataTable vào DataSet
int nRecs = da.Fill(ds); // trả về số lượng record được
nạp vào DataTable
// Nếu muốn đặt tên cho DataTable trong DataSet thay vì
lấy tên mặc định
// thì sử dụng code như thế này
int nRecs = da.Fill(ds, "nhanvien ")
Với một table đang tồn tại, tác dụng của lệnh Fill tùy thuộc vào table
có primary hay không. Nếu có, những dòng dữ liệu có khóa trùng với dòng dữ liệu
mới sẽ được thay thế. Các dòng dữ liệu mới không trùng với dữ liệu hiện có sẽ được
nối vào sau DataTable.
6.6.3. Cập nhật CSDL bằng DataAdapter
Sau khi DataAdapter đã nạp dữ liệu vào table, connection sẽ được đóng, và
các thay đổi sau đó đối sau đó tạo ra cho dữ liệu sẽ chỉ có ảnh hưởng trong DataSet
chứ không phải là ở dữ liệu nguồn! Để thực sự cập nhật các thay đổi này lên nguồn
dữ liệu, DataAdapter phải được sử dụng để khôi phục connection và gửi các dòng dữ
liệu đã được thay đổi lên CSDL.
Ngoài SelectCommand, DataAdapter có thêm 3 thuộc tính Command
nữa, gồm InsertCommand, DeleteCommand và UpdateCommand, làm nhiệm vụ
thực hiện các thao tác tương ứng với tên thuộc tính của chúng (chèn, xóa, cập
nhật). Các Command này được thực thi khi phương thức Update của DataAdapter
được triệu gọi. Khó khăn nằm ở chỗ tạo ra các query command phức tạp này (cú pháp
của câu lệnh SQL tương ứng càng dài dòng và phức tạp khi số lượng column nhiều
lên). Rất may là các data provider đều có cài đặt một lớp gọi là CommandBuilder
dùng để quản lý việc tạo các Command nói trên một cách tự động.
3.6.3.1. CommandBuilder
Một đối tượng CommandBuilder sẽ sinh ra các Command cần thiết để thực
hiện việc cập nhật nguồn dữ liệu tạo ra bởi DataSet. Cách tạo đối tượng

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 88


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

CommandBuilder là truyền đối tượng DataAdapter cho phương thức khởi dựng
của nó; sau đó, khi phương thức DataAdapter.Update được gọi, các lệnh SQL sẽ
được sinh ra và thực thi. Đoạn code dưới đây minh họa cách thức thay đổi dữ liệu ở
một DataTable và cập nhật lên CSDL tương ứng bằng DataAdapter:
//Giả sử đã có 1 DataSet ds chứa dữ liệu của bảng khoa
DataTable dt= ds.Tables["khoa"];
// (1) Dùng commandBuilder để sinh ra các Command cần thiết để update
SqlCommandBuilder sb = new SqlCommandBuilder(da);
// (2) Thực hiện thay đổi dữ liệu: thêm 1 khoa mới
DataRow drow = dt.NewRow();
drow["Makhoa"] = 12;
drow["tenkhoa"] = "abc";
dt.Rows.Add(drow);
// (3) Thực hiện thay đổi dữ liệu: xóa 1 khoa
dt.Rows[4].Delete();
// (4) Thực hiện thay đổi dữ liệu: thay đổi giá trị 1 dòng dữ liệu
dt.Rows[5]["tenkhoa"] = "this must be changed";
// (5) Tiến hành cập nhật lên CSDL
int nUpdate = da.Update(ds, "khoa");
MessageBox.Show("Số dòng được thay đổi: " + nUpdate.ToString());
Có một số hạn chế khi sử dụng CommandBuilder: Command Select ứng với
DataAdapter chỉ được tham chiếu đến 1 table, và table nguồn trong CSDL phải bao
gồm một primary key hoặc một column chứa các giá trị duy nhất. Column này (hay
tổ hợp các columns) phải được bao gồm trong command Select ban đầu.
3.6.3.2. Đồng bộ hóa dữ liệu giữa DataSet và CSDL
Như đã minh họa trong ví dụ này, việc sử dụng DataAdapter làm đơn giản hóa
và tự động hóa quá trình cập nhật CSDL hoặc bất kỳ data source nào. Tuy nhiên, có
một vấn đề ở đây: multi-user (nhiều người sử dụng). Mô hình Ngắt kết nối
được dựa trên cơ chế Optimistic Concurrency, một cách tiếp cận mà trong đó các
dòng dữ liệu ở data source không bị khóa (lock) giữa thời gian mà chúng được
đọc và thời gian mà các cập nhật được áp dụng cho data source. Trong khoảng
thời gian này, user khác có thể cũng cập nhật data source. Nếu có thay đổi xảy ra kể
từ lần đọc trước đó thì phương thức Update sẽ nhận biết được và không cho áp dụng
thay đổi đối với các dòng dữ liệu đó.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 89


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Có hai phương án cơ bản để giải quyết lỗi concurrency (tương tranh) khi có
nhiều cập nhật được áp dụng: roll back tất cả các thay đổi nếu như xuất hiện
xung đột (violation), hoặc áp dụng các cập nhật không gây ra lỗi và xác định những
cập nhật có gây ra lỗi để có thể xử lý lại.
6.7. Lựa chọn giữa mô hình Kết nối và mô hình Ngắt kết nối
DataReader và DataSet đưa ra hai cách tiếp cận khác nhau để xử lý dữ liệu.
DataReader cho phép truy xuất kiểu forward-only, read-only. Bằng cách xử lý từng
dòng một, cách tiếp cận này giúp tiết kiệm bộ nhớ. DataSet, ngược lại, cho
phép truy xuất theo kiểu read/write, nhưng lại yêu cầu phải có đủ bộ nhớ để quản
lý bản sao dữ liệu nạp về từ data source. Như vậy, bạn có thể suy ra một số quy tắc
chung: Nếu ứng dụng không cần tính năng cập nhật dữ liệu và hầu như chỉ hiển thị
và chọn lọc dữ liệu, DataReader là lựa chọn thích hợp; nếu ứng dụng cần cập nhật dữ
liệu, giải pháp sử dụng DataSet nên được xem xét.
Tất nhiên, cũng có một số tình huống đi ngược lại với các quy tắc chung nói
trên. Chẳng hạn, nếu data source chứa một số lượng lớn các record, khi đó DataSet
phải yêu cầu quá nhiều tài nguyên bộ nhớ; hoặc nếu dữ liệu chỉ yêu cầu một vài thao
tác cập nhật, thì sự kết hợp giữa DataReader và Command để thực thi cập nhật sẽ có
thể có ý nghĩa hơn.
Tóm lại, một DataSet là một lựa chọn tốt khi:
- Dữ liệu cần được serialize (tuần tự hóa) và/hoặc gửi đi bằng HTTP.
- Các điều khiển read-only trên Form Win Form được kết buộc (bind)
với data source.
- Một điều khiển Win Form như GridView hay DataView được kết buộc với
một data source có khả năng cập nhật được.
- Một ứng dụng desktop cần thêm, xóa, sửa các dòng dữ liệu.
Trong khi đó, DataReader là lựa chọn cho những trường hợp:
- Cần quản lý một số lượng lớn các record, lớn đến mức mà bộ nhớ và thời
gian để nạp dữ liệu cho DataSet là phi thực tế.
- Dữ liệu là read-only và được kết buộc với một điều khiển loại danh
sách (list control) của Win Form hoặc Web Form.
- CSDL là không ổn định và thay đổi thường xuyên.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 90


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

BÀI TẬP CHƯƠNG 6


Câu 1: Tạo form nhập liệu như sau:

Câu 2: Tạo form nhập liệu có định dạng và yêu cầu như sau:

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 91


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 92


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

CHƯƠNG 7: BÁO CÁO


7.1. Crystal Report
Crystal Report là phần mềm thiết kế báo biểu chuyên nghiệp được tích hợp trong
các phiên bản của Visual Studio. Phiên bản Studio .NET của Microsoft được tích hợp
Crystal Report.
Bản thân Crystal Report là một phần mềm tạo báo biểu độc lập với rất nhiều
chức năng thiết kế báo biểu và dịch vụ. Người dùng có thể kết nối với nhiều nguồn
dữ liệu khác nhau bằng các ODBC Driver.
Báo biểu khi tạo ra cũng có thể được lưu trữ thành những file .rpt độc lập, ở
dạng có dữ liệu hay không có dữ liệu. Sau đó, file .rpt có thể được chuyển tới người
dùng khác và mở bằng Crystal Report hay có thể kết hợp với các ứng dụng viết bằng
Visual Basic, Visual C++.
Xét về mặt thiết kế báo biểu, Crystal Report cung cấp đầy đủ các chức năng
đinh dạng dữ liệu và các chức năng phân nhóm, tính toán, sub – report và kể cả khả
năng lập trình bằng formula dựa trên các fomula field. Người dùng ngoài việc sử
dụng formula field còn có thể tự xây dựng bộ thư viện hàm của riêng mình và đưa
vào Crystal Report thông qua các DLL. Bên cạnh khả năng thiết kế báo biểu thông
thường, Crystal Report còn cung cấp chức năng thiết kế biểu đồ dựa trên nguồn dữ
liệu lấy từ CSDL.
Xét về mặt sử dụng báo biểu, công cụ hiển thị của Crystal Report cho phép
người dùng tương tác rất linh hoạt. Báo biểu hiển thị có thể được lọc lại các dữ liệu
cần thiết hay xem một phần báo biểu bằng cách sử dụng cấu trúc hiển thị dữ liệu dạng
cây. Các Section trong báo biểu cũng có thể mở rộng hay thu hẹp để hiển thị hay che
bớt những dữ liệu không cần thiết. Một khi báo biểu đã được xây dựng, người dùng
còn có thể Export sang các dạng file khác như Word, Excel, HTML,…
Bằng cách tích hợp Crystal Report, Visual Studio .NET đem lại cho người dùng
một công cụ xây dựng báo biểu hiệu quả, tiết kiệm nhiều thời gian so với việc phải
sử dụng các đối tượng in ấn để tự phát sinh báo biểu. Chúng ta có thể sử dụng Report
Expert để tạo ra báo biểu dựa vào wizard và template định sẵn hay thiết kế chi tiết
báo biểu bằng tay. Trong giáo trình này chỉ hướng dẫn cách tạo báo biểu bằng wizard.
7.2. Hướng dẫn sử dụng report wizart.
Thiết kế form lọc dữ liệu theo mẫu sau.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 93


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

Form cho phép người sử dụng chọn tên một nhân viên bán hàng trong cboten
và hiển thị thông tin chi tiết về những hóa đơn bán hàng của nhân viên đó. Khi nhấn
nút Report ta sẽ xuất dữ liệu trên form sang một report được thể hiện như hình sau:

Phần hiển thị và lọc dữ liệu được thực hiện thông qua đối tượng dataAdapter và
đối tượng DataSet như đã hướng dẫn trong các ví dụ trước.
Vấn đề chỉ còn lại cách xây dựng báo biểu thống kê chi tiết các lần bán hàng
theo tên nhân viên và viết code cho nút Report. Hãy thực hiện theo các bước sau:
- Bước 1: Trong SQL Server tạo thủ tục nhận tên người bán làm tham số và trả
về thông tin bán hàng của nhân viên đó. Thủ tục có tên thongkeBHtheoNV và được
tạo như sau:
Create proc ThongkeBHtheoNV(@tennb nvarchar(50))
as
begin
select banhang.sohd,
banhang.ngayban,banhang.nguoiban,

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 94


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

banhang.masp,sanpham.tensp,sanpham.dongia,
banhang.soluong,banhang.thanhtien
from sanpham,banhang
where banhang.masp=sanpham.masp and
banhang.nguoiban=@tennb
end
Biên dịch thủ tục trên (nhấn F5)
- Bước 2:
+ Tạo Crystal Report (nhấn phải chuột vào tên project trong cửa sổ Solution
Explorer, chọn Add, chọn Reporting, chọn Crystal Report).
+ Đặt tên report là rptTK_TheoNV. Cửa sổ Crystal Reports Gallery xuất hiện
như hình dưới đây. Chọn kiểu Standard và nhấn OK.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 95


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

- Bước 3: Nháy đúp vào mục Create New Connection; chọn OLEDB, chọn
Microsoft OLEDB Provider for SQL Server, chọn Next

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 96


Bài giảng Lập trình windows với C# Khoa Công nghệ thông tin

+ Chọn tên Server và tên Database. Nhấn Next sang bước tiếp theo.
+ Tìm tên thủ tục ThongkeBHtheoNV trong danh mục các thủ tục nội tại của
cơ sở dữ liệu. Add sang bảng Selected Table. Nhấn Next để tiếp tục.
+ Add toàn bộ các trường của thủ tục ThongkeBHtheoNV sang cửa sổ bên phải.
Nhấn Finish để hoàn tất bước 3. Report rptTK_theoNV đã xuất hiện trên project.
- Bước 4: Định dạng lại report như hình dưới đây. Section1 là phần tiêu đề của
báo biểu; Section 2 là tiêu đề các cột của bảng (lặp lại khi hết một trang); Section3
là phần dữ liệu tương ứng với một bản ghi.

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 97


Bài giảng Lập trình Windows với C# Khoa Công nghệ thông tin

+ Dùng Text Object để đặt các label lên báo biểu; Line Object để vẽ các đường
thẳng; dùng cửa sổ Field Explorer để chèn các trường vào báo biểu.
+ Để định dạng nội dung, font chữ, kiểu dữ liệu của tiêu đề cột và dữ liệu trong
cột, nhấn phải chuột vào đối tượng và chọn các lệnh cần thiết.
Thủ thuật: Để gióng hàng (hoặc đặt cùng kích cỡ) cho nhiều đối tượng, bạn chọn
chúng và nhấn phải chuột chọn Align hoặc Size.
+ Để xem trước báo biểu, chọn nút Main Report Preview.
- Bước 5: Tạo form làm lớp cơ sở cho báo biểu:
+ Tạo form mới, đặt tên form là frmTK_theoNV.
+ Đưa vào form một điều khiển CrystalReportViewer. Điều khiển có tên ngầm
định là CrystalReportViewer1
- Bước 6: Viết code cho nút Report và chạy thử chương trình

Giáo viên biên soạn: Trương Mỹ Thu Thảo Trang 98

You might also like