This blog post is actually a prelude to next post "Custom Shaped Areas In VB.NET". When trying to write that one, It came to me that the knowledge on how to add controls at run-time is required, and so I wrote this one first.
We start with the basics.
As you probably know, When you add a component to from the toolbox to the form(eg: Form1), Visual Studio will automatically create the code required for that in the corresponding .designer.vb file (in this example it's Form1.Designer.vb).
You can open that file, in variable declaration for the component you just added to the form, as well as some code for location and stuff. That's what we call "adding controls at design time", as opposed to what we're going to do now, that is "adding controls at run-time". We are going to use similar codes with the one generated by Visual Studio during design time.
All controls we're going to add, must be placed inside a container. Be it a Form, a GroupBox or a Panel. For our uses now, we are going to use a Panel, so that it won't interfere with other controls that we placed in the form.
Double click on both btnAdd and btnClear to create event handler procedures for both buttons (for buttons, it's the default 'click' event')
In procedure btnAdd_Click, we will try to add a button to the panel. Use this code :
Try to run the program, and you can click the Add Button, and in the panel, a button would appear.
The next thing we're going to do is to remove the button. In the procedure btnClear_Click, Use this code:
You can try to run the program again. Click the Add button to make the button appear and click on the Clear button to make the button disappear.
Brief explanation :
- In btnAdd_Click, we declare a button (and in the same time instantiate it with the keyword New). And then we give it some text and add the button to the Panel, specifically the 'Controls' property which is a collection of all the controls in a container type control (in this case a panel).
You can click add Button many times, and it will create more buttons, although it will all be placed in the same location because we didn't provide any code for the coordinate). - In btnClear_Click, we just remove all controls inside the panel using the Clear method of the 'Controls' property.
- If you previously have knowledge of "collections", you will know that you can access individual controls inside the controls property using the zero based index of the said item, and that the controls property have all the basic method that a "colllection" have.
For example, you can access the first button in the panel using PnlButtons.Controls(0), and you can type . (dot) after pnlButtons.Controls, to see what properties and methods that the 'Controls' collection can do
Okay, now let's escalate things a bit. We gonna use a bit of code so that when you click on the add button, 10 buttons will be added to the panel, in different locations.
Change the AutoScroll properties of pnlButtons to True so that when we add a lot of buttons and their coordinates is larger than the panel's width, a scrollbar automatically appear
Change the contents of btnAdd_Click to this :
Try to run the program, and 10 buttons will appear when you click the Add Button.
And now let's talk about event handling of those buttons. How do we do that ?
Let's look at the procedure btnAdd_Click. You can see that it has a function signature like this.
If you've been using .NET for a while you would know that parameter sender refers to the object sending the event (in this case btnAdd), and parameter e contains information about the event (in this case, a button click event, e doesn't contain any useful information, but in events like MouseMove, it will be different type than System.EventArgs, and you can look at the properties to find information such as the X & Y coordinates of the mouse).
The last part said that it Handles btnAdd.Click event. We can use the keyword handles here, because btnAdd has been previously declared in Form1.Designer.vb (and with the keyword WithEvents too!).
We can't use this for buttons we added at run-time, but rather, we also must bind their events with code.
Now, Add another event handler procedure similar to the btnAdd_Click. Use a different name but the same parameters and omit the handles keyword
Change the contents of btnAdd_Click to this :
As you notice, we are only adding one line, that is the Addhandler line, where we bind the click event of the button we just created with the procedure Btn_Click earlier.
Run the program, and notice that everytime you click on the newly added buttons, it will show a MessageBox.
The next part is how to differentiate which button we clicked. We could just change the contents of the btn_click to this :
MessageBox.Show("You Clicked Button " & Sender.Text)
But if you notice, when you type the dot after Sender, there is no assistance from Intellisense, because sender is declared as type System.Object in the parameter declaration. the more elegant approach would be to typecast sender to its original class (that is a Button)
Run the program, and notice now that when you click on the newly added buttons, it will show the text of that button.
Well, that's for our brief tutorial.
Indonesian Version
Post kali ini sebenarnya adalah pendahuluan untuk post yang judulnya "Custom Shaped Areas In VB.NET". Waktu lagi nyoba nulis yang itu, gue ngerasa perlu untuk membahas dulu mengenai menambahkan komponen pada saat program lagi berjalan (saat run-time)
Ok, dasarnya dulu.
Waktu kita menambahkan komponen dari toolbox ke form (Form1), Visual Studio akan menambahkan scara otomatis kodingnya di file Form1.Designer.vb. Kalau kita buka file itu, kita bisa lihat bagian-bagian yang ditambahkan secara otomatis tersebut, seperti deklarasi variabel, posisi dan sebagainya. Proses ini kita sebut menambahkan komponen saat design time. Sedangkan yang kali ini kita bahas adalah mengenai menambahkan komponen saat run-time (program berjalan). Nanti koding yang kita tambahkan akan mirip dengan koding yang ditambahkan Visual Studio tadi.
Semua komponen yang kita tambahkan, harus ditambahkan ke dalam sebuah Container (contoh container : Form, GroupBox atau Panel). Kali ini kita akan pakai panel, supaya gak nyampur dengan komponen lain yang kita taruh di form.
Tambahkan 1 panel dan 2 button ke form kita. Panelnya dikasih nama pnlButtons, buttonnya btnAdd dan btnClear.
Dobel klik di btnAdd dan btnClear. Visual Studio akan otomatis menambahkan prosedure event handler untuk kedua tombol tersebut (untuk button, event handler defaultnya untuk event click).
Di dalam procedure btnAdd_Click, pakai koding berikut :
Coba jalankan programnya, dan kalau kita coba klik tombol Add, nanti di panelnya, akan muncul 1 button.
Lanjutttt.
Untuk menghilangkan tombol yang sudah kita tambahkan. tambahkan koding berikut di procedure btnClear_Click
Coba jalankan, dan klik Add kemudian klik Clear.
Penjelasan singkat :
- Di btnAdd_Click, kita deklarasikan tombol (dan sekaligus bikin instance-nya dengan keyword New). Kita set properti Text dan kita tambahkan ke panelnya. Lebih tepatnya sih ke property 'Controls' dari panel tersebut. Properti Controls adalah Collection dari semua control di dalam komponen yang tipenya kontainer (dalam hal ini, panel). Kita bisa klik berkali-kali tombol Add, dan akan menambahkan berkali-kali juga tombol tersebut, walaupun hasilnya akan bertumpuk di koordinat yang sama
- Di btnClear_Click, kita buang SEMUA komponen yang ada di panel tersebut dengan menggunakan fungsi Clear dari properti Controls.
- Kalau sebelumnya pernah belajar mengenai "Collection", pasti tahu kalau kita bisa mengakses masing-masing anggota property Controls tersebut dengan menggunakan indeks (mulai dari 0), dan bahwa Controls akan memiliki properti dan method yang standar dengan "Collection" lainnya.
Misalnya, kita bisa mengakses item pertama di Controls dengan menggunakan pnlButton.Controls(0), dan kalau kita ketik dot (titik) setelah pnlButtons.Controls, kita bisa lihat properti dan method yang tersedia untuk sebuah 'Collection'
Ok, kita lanjut sedikit. Kita ganti kodingnya supaya waktu diklik add, tombolnya nambah lebih banyak, dengan koordinat yang berbeda supaya gak numpuk.
Sebelumnya kita ganti properti AutoScroll di Panel tersebut jadi True, supaya nanti kalau kita udah nambahkan komponen sehingga gak muat di panel tersebut, nanti otomatis keluar scrollbar-nya.
Ganti isi btnAdd_Click sbb:
Kita coba jalankan lagi programnya, dan waktu kita klik tombol add, sekarang bertambah 10 buah button.
Trus sekarang gimana kalau tombol-tombol tersebut. Gimana caranya untuk menangkap event tersebut (dan nanti juga mengenali tombol mana yang diklik) ?
Kita lihat procedure btnAdd_Click, kita lihat bentuknya seperti ini
Kalau udah lumayan sering pakai .NET, mustinya tahu kalau parameter sender itu adalah object yang mengirimkan event, dan parameter e adalah informasi mengenai event tersebut. Untuk contoh ini (tombol diklik, parameter e tidak mengandung informasi yang berguna, tapi di event lain, misalnya I, e-nya tidak bertipe System.Eventargs doang, dan kita bisa cek property-nya untuk dapat informasi, misalnya koordinat X dan Y dari Mouse)
Potongan terakhir menyebutkan bahwa procedure ini menghandle event Click-nya btnAdd. Cara ini bisa dipakai karena kalau kita lihat di Form1.Designer.vb, btnAdd itu SUDAH dideklarasikan (yang juga ada tambahan keyword WithEvents). Kita gak bisa pakai cara ini untuk tombol yang kita tambahkan saat runtime (karena belum dideklarasikan saat design).
Tambahkan procedure baru yang serupa dengan btnAdd_Click (copy paste saja, diganti dikit : nama dibedakan, parameter sama, bagian handles dibuang)
Ganti isi procedure btnAdd_Click sbb:
Kita sebenarnya hanya nambah 1 baris, yaitu bagian AddHandler, dimana kita mengaitkan event click dari button yang kita baru buat dengan procedure Btn_Click. Jalankan programnya, dan sekarang setiap kali kita klik tombol-tombol tersebut, akan keluar Messagebox.
Berikutnya adalah bagaimana membedakan setiap tombol yang diklik itu. Kita bisa saja mengganti isi procedure Btn_Click menjadi MessageBox.Show("You Clicked Button " & Sender.Text)
Tapi kalau diperhatikan, waktu kita ketik tanda . setelah sender, intellisense-nya tidak mengeluarkan property Text. Ini karena Sender itu dideklarasikan di parameternya sebagai tipe generik System.Object.
Cara yang lebih 'elegan' adalah dengan mengkonversi sender itu ke tipe aslinya (yaitu Button)
Jalankan lagi programnya, dan sekarang setiap kali kita klik tombol, Messagebox-nya akan berisi teks dari setiap tombol yang kita klik.
Sekian tutorial singkat ini.
No comments:
Post a Comment