Mục tiêu Luyện tập với các control thể hiện danh sách như: ListView, TreeView.. Việc này để hiểu rõ bản chất của gắn kết event nhằm dễ dàng thực hiện khi các control là tự tạo trong code
Trang 1Mục tiêu
Luyện tập với các control thể hiện danh sách như: ListView, TreeView
Nội dung
Sửa Bài tập tuần 01
- Bước 1: Xây dựng giao diện form chính như sau
- Bước 2: Tạo form mới tên là Form2
- Bước 3: Code trong Form1.cs như sau
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
btnCreate.Click += btnCreate_Click;
}
void btnCreate_Click(object sender, EventArgs )
{
int nr, nc;
if (!int.TryParse(txtNumR.Text, out nr))
nr = 3;
if (!int.TryParse(txtNumC.Text, out nc))
nc = 3;
Form2 frm = new Form2(nr, nc);
frm.StartPosition = FormStartPosition.CenterScreen;
frm.ShowDialog();
}
}
Ở đây thực hiện gắn kết event bằng code (không thông qua design) Việc này để hiểu rõ bản chất của gắn kết event nhằm dễ dàng thực hiện khi các control là tự tạo trong code chứ không qua design (Ở Form2)
- Bước 4: Code trong Form2.cs như sau
btnCreate
Trang 2public partial class Form2 : Form
{
int margin = 5, padding = 2, s = 30;
public Form2()
{
InitializeComponent();
}
public Form2(int nr, int nc)
{
InitializeComponent();
Button btn = null;
for(int =0; i nr; ++i)
{
for(int =0; j nc; ++j)
{
btn = new Button();
btn.Width = s;
btn.Height = s;
btn.Text = (i * nc + j).ToString();
btn.Top = margin + i * (s + padding);
btn.Left = margin + j * (s + padding);
Controls.Add(btn);
btn.Click += btn_Click;
btn.Tag = string.Format("{0}, {1}", i, j);
}
}
ClientSize = new Size((s + padding) * nc + margin * 2, (s + padding) * nr + margin * 2);
}
void btn_Click(object sender, EventArgs )
{
MessageBox.Show((sender as Control).Tag.ToString());
}
}
Chú ý: để truyền tham số về số dòng và số cột cho Form2 thì cách đơn giản là sử dụng phương thức khởi tạo có đối số của Form2 (tự xây dựng)
Đối với những thông số như: kích thước, mức canh lề,… thì nên đặt trong giá trị biến để dễ dàng thay đổi (không code cứng kiểu: btn.Width = 20;)
- Bước 5: Chạy chương trình
Sử dụng ListView và TreeView
Xây dựng 1 chương trình quản lý lớp học đơn giản
- Bước 1: Tạo frmMain với giao diện như sau
Lựa chọn SplitContainer từ menu Container của ToolBox
Trang 3 Thay đổi thuộc tính Orientation để hiển thị theo chiều ngang hay dọc
thuộc tính FixedPanel để cố định kích thước 1 panel (chỉ được phép cố định 1 panel)
Chú ý thuộc tính Dock là Fill để ListView và TreeView chiếm trọn vùng
Giao diện cuối cùng (sử dụng 2 SplitContainer với 1 theo chiều ngang và 1 theo chiều dọc)
Trang 4- Bước 2: Xây dựng các lớp dữ liệu
Class HocSinh
public class HocSinh
{
public string HoTen { get; set; }
}
Class LopHoc
public class LopHoc
{
public string TenLop { get; set; }
public List<HocSinh> ListHocSinh { get; set; }
}
Class TruongHoc
public class TruongHoc
{
public string TenTruong { get; set; }
public List<LopHoc> ListLopHoc { get; set; }
}
- Bước 3: Code các xử lý cho frmMain (trong frmMain.cs, class frmMain)
Thực hiện tạo phần tử cho ComboBox
static string[] arrViewMode = new string[] { "Large Icon", "Details",
"Small Icon", "List", "Tile" };
void FillComboBox()
{
cbLvView.Items.Clear();
foreach(string str in arrViewMode)
{
btnLoad
cbLvView
tv
lv
Trang 5cbLvView.Items.Add(str);
}
if (cbLvView.Items.Count > 0)
{
cbLvView.SelectedIndex = 1;
}
}
Lưu ý: sử dụng mảng lưu giá trị các phần tử để thực hiện vòng lặp dễ dàng (code ngắn và mạch lạc hơn)
Viết code cho phương thức khởi tạo của frmMain
public frmMain()
{
InitializeComponent();
btnLoad.Click += new EventHandler(btnLoad_Click);
cbLvView.SelectedIndexChanged += new
EventHandler(cbLvView_SelectedIndexChanged);
FillComboBox();
//với TreeView thì event mặc định là AfterSelect
tv.AfterSelect += new TreeViewEventHandler(tv_AfterSelect);
//với ListView vì mục đích sử dụng là duyệt file nên
//chỉ xử lý event DoubleClick
lv.DoubleClick += new EventHandler(lv_DoubleClick);
}
Viết code cho event Click của Button
void btnLoad_Click(object sender, EventArgs )
{
FillTreeView();
}
Với hàm tạo dữ liệu cho TreeView như sau
static string[] arrHo = new string[] { "Trần", "Ngô", "Lê", "Nguyễn",
"Phạm", "Bùi" };
static string[] arrTenLot = new string[] { "Thị", "Văn", "Thanh", "Anh",
"Duy", "Đăng", "Minh" };
void FillTreeView()
{
Random rd = new Random();
int nTruongHoc = rd.Next(3, 10);
int nLopHoc = 0, nHocSinh = 0;
int iHo = 0, iTenLot = 0;
TreeNode tnTH = null, tnLH = null;
TruongHoc th = null;
LopHoc lh = null;
HocSinh hs = null;
for (int iTH = 0; iTH < nTruongHoc; ++iTH)
{
th = new TruongHoc()
{
Trang 6ListLopHoc = new List<LopHoc>(),
TenTruong = string.Format("Trường {0}", iTH + 1)
};
//tạo node trường học
tnTH = new TreeNode(th.TenTruong);
//giữ lại reference TruongHoc để sử dụng khi cần
tnTH.Tag = th;
//đưa vào node gốc của TreeView
tv.Nodes.Add(tnTH);
//tạo lớp học
nLopHoc = rd.Next(3, 10);
for (int iLH = 0; iLH < nLopHoc; ++iLH)
{
lh = new LopHoc()
{
ListHocSinh = new List<HocSinh>(),
TenLop = string.Format("Lớp {0} (của trường {1})", iLH +
1, iTH + 1)
};
th.ListLopHoc.Add(lh);
//tạo node lớp học
tnLH = new TreeNode(lh.TenLop);
tnLH.Tag = lh;
tnTH.Nodes.Add(tnLH);
//tạo học sinh
nHocSinh = rd.Next(10, 20);
for (int iHS = 0; iHS < nHocSinh; ++iHS)
{
iHo = rd.Next(arrHo.Length - 1);
iTenLot = rd.Next(arrTenLot.Length - 1);
hs = new HocSinh()
{
HoTen = string.Format("{0} {1} {2}", arrHo[iHo], arrTenLot[iTenLot], (char)(0x41 + rd.Next(25)))
};
lh.ListHocSinh.Add(hs);
}
}
}
}
Ở đây dữ liệu được tạo ngẫu nhiên, điểm mấu chốt cần nắm là thứ tự đưa phần
tử vào TreeView phải đảm bảo mức phân cấp
Viết code cho event SelectedIndexChanged của ComboBox
void cbLvView_SelectedIndexChanged(object sender, EventArgs )
{
//luôn kiểm tra selectedIndex trước khi sử dụng
if (cbLvView.SelectedIndex >= 0)
{
//vì ViewMode của ListView đặt giá trị theo enum
//nên dễ dàng ánh xạ với index
lv.View = (View)cbLvView.SelectedIndex;
}
Trang 7}
Viết code cho event AfterSelect của TreeView
void tv_AfterSelect(object sender, TreeViewEventArgs )
{
//lấy đối tượng đã giữ trong Tag
var th = e Node.Tag as TruongHoc;
//xét nếu không phải là TruongHoc
if (th == null)
{
FillListView( Node.Tag as LopHoc);
}
else
{
FillListView(th);
}
}
Với hàm thêm phần tử cho ListView như sau (ở đây có 2 trường hợp khi lựa chọn TruongHoc hay LopHoc ở TreeView nên có 2 phiên bản hàm)
void FillListView(TruongHoc th)
{
//xóa ListView
lv.Clear();
//thêm cột
ColumnHeader ch = new ColumnHeader();
ch.Text = "Tên lớp";
ch.Width = 200;
lv.Columns.Add(ch);
ch = new ColumnHeader();
ch.Text = "Trường";
ch.Width = 200;
lv.Columns.Add(ch);
//thêm phần tử
//luôn ghi nhớ item của ListView là ListViewItem
ListViewItem lvi = null;
foreach (LopHoc lh in th.ListLopHoc)
{
lvi = new ListViewItem(lh.TenLop);
lvi.SubItems.Add(th.TenTruong);
//với ListViewItem cũng có Tag để sử dụng
lvi.Tag = lh;
lv.Items.Add(lvi);
}
}
void FillListView(LopHoc lh)
{
//xóa ListView
lv.Clear();
//thêm cột
ColumnHeader ch = new ColumnHeader();
ch.Text = "Họ tên";
Trang 8ch.Width = 200;
lv.Columns.Add(ch);
ch = new ColumnHeader("Lớp");
ch.Text = "Lớp";
ch.Width = 200;
lv.Columns.Add(ch);
//thêm phần tử
ListViewItem lvi = null;
foreach (HocSinh hs in lh.ListHocSinh)
{
lvi = new ListViewItem(hs.HoTen);
lvi.SubItems.Add(lh.TenLop);
lvi.Tag = hs;
lv.Items.Add(lvi);
}
}
Cuối cùng là viết code cho event DoubleClick của ListView
void lv_DoubleClick(object sender, EventArgs )
{
//kiểm tra item của listView có được chọn
if (lv.SelectedItems.Count > 0)
{
ListViewItem lvi = lv.SelectedItems[0];
var lh = lvi.Tag as LopHoc;
if (lh != null)
{
FillListView(lh);
}
}
}
- Bước 4: Chạy chương trình
Bài tập
Hoàn thành bài ListView và TreeView ở trên
Viết chương trình ví dụ về 2 loại UserControl (Extended và Composite)