Makale Özeti

ASP.NETte Datagrid hakkında sıkça sorulan sorulardan biri de düzenleme yaparken, DataGridin kendi koyduğu textboxlar yerine nasıl comboboxlar ekleneceğidir.

Makale

DATAGRIDTE DROPDOWNLIST KULLANIMI

ASP.NETte Datagrid hakkında sıkça sorulan sorulardan biri de düzenleme yaparken, DataGridin kendi koyduğu textboxlar yerine nasıl comboboxlar ekleneceğidir. Bu sorunun belli başlı iki çözümü var. Birincisi DataGridin ItemDataBound ve ItemCreated olaylarını kullanarak, ikincisi de Template Column kullanarak.
Bu makalede iki çözümü de örnek üzerinde anlatacağım. Bunun için SQL Serverdaki Northwind databaseindeki ve Orders tablosunu kullnacağım.


ÇÖZÜM 1- ITEM CREATED VE ITEMDATABOUND KULLANARAK DROPDOWNLIST OLUŞTURMAK:

1- Formun her proesdüründen erişilebilmesi için, Global olarak tanımlanmış Dataset , DataAdaptor ve Connection nesneleri yaratlım.
2- Datagridimizde Property Builder kullanrak OrderID (read only) ,CompanyName,Ship Adress ve CustomerID (invisible) Bound Columnlarını ekleyelim.(Hepsi Bound Column). Düzenlemeler için de bir adet Edit button column ekleyelim.Sırası yukarıdaki resimdekiyle aynı olsun. HTML kodları şu şekilde olması lazım:

<asp:datagrid id="DataGrid1" runat="server" BorderColor="#E7E7FF" BorderStyle="None" BorderWidth="1px"
BackColor="White" CellPadding="3" GridLines="Horizontal" AutoGenerateColumns="False">
<SelectedItemStyle Font-Bold="True" ForeColor="#F7F7F7" BackColor="#738A9C"></SelectedItemStyle>
<AlternatingItemStyle BackColor="#F7F7F7"></AlternatingItemStyle>
<ItemStyle ForeColor="#4A3C8C" BackColor="#E7E7FF"></ItemStyle>
<HeaderStyle Font-Bold="True" ForeColor="#F7F7F7" BackColor="#4A3C8C"></HeaderStyle>
<FooterStyle ForeColor="#4A3C8C" BackColor="#B5C7DE"></FooterStyle>
<Columns>
<asp:EditCommandColumn ButtonType="PushButton" UpdateText="Update" CancelText="Cancel" EditText="Edit"></asp:EditCommandColumn>
<asp:BoundColumn DataField="OrderID" ReadOnly="True" HeaderText="Siparis ID"></asp:BoundColumn>
<asp:BoundColumn DataField="CompanyName" HeaderText="M&#252;şteri Adı"></asp:BoundColumn>
<asp:BoundColumn DataField="ShipAddress" HeaderText="Sipariş Adresi"></asp:BoundColumn>
<asp:BoundColumn Visible="False" DataField="CustomerID" HeaderText="M&#252;şteri ID"></asp:BoundColumn>
</Columns>
<PagerStyle HorizontalAlign="Right" ForeColor="#4A3C8C" BackColor="#E7E7FF" Mode="NumericPages"></PagerStyle>
</asp:datagrid>

 

Dim Ds As New DataSet
Dim Con As New SqlConnection("Server=.;Database=Northwind;User ID=sa;Password=")
Dim daUrunler As New SqlDataAdapter("select o.OrderID,o.CustomerID,c.CompanyName,o.ShipAddress from orders as o join Customers as c on c.CustomerID=o.CUstomerID order by OrderID", Con)
3-Page Load olayında Datagridimizi DataSetimize bağlayalım. Bu kodun Postbacklerde çalışmaması için önlem de almalıyız.

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Page.IsPostBack = True Then Exit Sub
daUrunler.Fill(Ds)
Me.DataGrid1.DataSource = Ds
DataGrid1.DataBind()
End Sub

4- Edit Tuşuna/Linkine basıldığı zaman ilgili satırın işaretlenmesi için DataGridin EditCommand olayına şu kodları yazmalıyız:

Private Sub DataGrid1_EditCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles DataGrid1.EditCommand
Me.DataGrid1.EditItemIndex = e.Item.ItemIndex
daUrunler.Fill(Ds)
Me.DataGrid1.DataSource = Ds
DataGrid1.DataBind()
End Sub

5- Şimdi işin can alıcı noktasına geldik. Edit Item olayında yaratılan nesneleri yakalayıp, ilgili sürundan (ki burada CompanyName) Textboxı kaldırıp yerine combobox koymalıyız. İlk olarak Datagridin ItemCreated kısmına kodlarımızı yazalım.
If e.Item.ItemType = ListItemType.EditItem Then
Dim SilinecekTextBox As TextBox
SilinecekTextBox = e.Item.Controls(2).Controls(0)
e.Item.Controls(2).Controls.Remove(SilinecekTextBox)

Dim com As New SqlCommand("Select CompanyName,CustomerID from Customers", Con)
Dim dr As SqlDataReader
Dim EklenecekDropDownList As New DropDownList
Con.Open()
dr = com.ExecuteReader

While dr.Read
Dim MenuElemanlari As New ListItem
MenuElemanlari.Text = dr("CompanyName")
MenuElemanlari.Value = dr("CustomerID")
EklenecekDropDownList.Items.Add(MenuElemanlari)
End While

Con.Close()

e.Item.Controls(2).Controls.Add(EklenecekDropDownList)
End If
End Sub


Burada özellikle belirtmem gereken bilgi şu: Satırlar oluşurken DataGridimiz, bir Table gibi davranır. "e.Item.Controls(0)" derken aslında bir TableCellden bahsederiz. Eğer bu hücrede başka bir nesne varsa (textbox,dropdownlist vs gibi), bunlara da bu hücrenin controls özelliğiyle erişiriz. ( e.Item.Controls(0).controls(0) gibi) Yani biz e.Item.Controls(0).controls(0) demekle DataGridin tablosunun seçili satırının 0 indexli hücresinin 0 indexli nesnesinden bahsederiz aslında. (ki örneğimizde bu kontrol "Edit" butonuna eşit)
Biz, Textbox yerine DropDownList kullanacağımız için öncelikle CompanyNamein yazılı olduğu Textboxı silmemiz gerekir. CompanyName 3.sütunda bulunmaktadır. Indexlerin 0dan başladığı gözönüne alınırsa 2. indexe denk gelir. Yani "e.Item.Controls(2)" textboxun bulunduğu hücreyi verir. O hücrede sadece bir tane nesne (ismin yazılı olduğu textbox) olduğu için textboxa da e.Item.Controls(2).controls(0) diyerek erişebilirirz.

Dim SilinecekTextBox As TextBox
SilinecekTextBox = e.Item.Controls(2).Controls(0)
e.Item.Controls(2).Controls.Remove(SilinecekTextBox)

Bundan sonraki işlem, silinen Textbox yerine Text özelliği "Customers" tablosundaki "CompanyName" sütunuyla ve Value özelliği de "CustomerID"siyle doldurulmuş bir Dropdownlist oluşturmaktır.

Dim EklenecekDropDownList As New DropDownList
Con.Open()
dr = com.ExecuteReader
While dr.Read
Dim MenuElemanlari As New ListItem
MenuElemanlari.Text = dr("CompanyName")
MenuElemanlari.Value = dr("CustomerID")
EklenecekDropDownList.Items.Add(MenuElemanlari)
End While
Con.Close()


DropdownListimiz oluştuktan sonra bunu DataGride eklememiz gerek.
e.Item.Controls(2).Controls.Add(EklenecekDropDownList)
satırlarıyla bunu da sağlamış oluyoruz.

6- Artık önümüzde tek bir engel kaldı. Düzenlenecek sütundaki CompanyNamei Dropdownlistte seçtirmek. Eğer bunu yapmazsak DropdownListte en baştaki isim seçili olarak gelecektir. Bu işi yapmak için DataGridin ItemDataBound olayını kullanıyoruz.

Private Sub DataGrid1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles DataGrid1.ItemDataBound
If e.Item.ItemType = ListItemType.EditItem Then
Dim EklenecekDropDownList As DropDownList
Dim MevcutCustomerID As TextBox
MevcutCustomerID = e.Item.Controls(4).Controls(0)
EklenecekDropDownList = e.Item.Controls(2).Controls(0)
EklenecekDropDownList.SelectedValue = MevcutCustomerID.Text
End If
End Sub

Ben burada Invisible olan CustomerIDnin değerini çektirerek DropDownListin SelectedValuesunu buldurdum. Ama burada tercih sizin. İsterseniz Datagridin bağlı olduğu Datasetten de CustomerIDyi alabilirsiniz. (İkinci örnekte bu şekilde yapılmıştır)

7- Düzenleme anında iptal tuşuna basıldığındaki kodlar:

Private Sub DataGrid1_CancelCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles DataGrid1.CancelCommand
Me.DataGrid1.EditItemIndex = -1
Me.daUrunler.Fill(Ds)
Me.DataGrid1.DataSource = Ds
Me.DataGrid1.DataBind()
End Sub

8- Kaydet düğmesine basıldığında ise DataGridin Update olayına aşağıdaki kodları yazarsak örneğimiz tamamlanmış olur.

Private Sub DataGrid1_UpdateCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles DataGrid1.UpdateCommand
Dim Sorgu As String
Sorgu = "Update Orders Set CustomerID=@CustomerID,ShipAddress=@ShipAddress where OrderID=@OrderID"
Dim com As New SqlCommand(Sorgu, Con)

Dim SeciliMusterininID As DropDownList
Dim Adres As TextBox
Dim OrderID As TableCell

OrderID = e.Item.Controls(1)
SeciliMusterininID = e.Item.Controls(2).Controls(0)
Adres = e.Item.Controls(3).Controls(0)

com.Parameters.Add("@CustomerID", SeciliMusterininID.SelectedValue)
com.Parameters.Add("@ShipAddress", Adres.Text)
com.Parameters.Add("@OrderID", OrderID.Text)
Con.Open()
com.ExecuteNonQuery()
Con.Close()

Me.DataGrid1.EditItemIndex = -1
daUrunler.Fill(Ds)
Me.DataGrid1.DataSource = Ds
DataGrid1.DataBind()

End Sub

Burada , OrderIDyi ikinci sütundaki değerden okuduk. Readonly olduğu için orada bir textbox oluşmadı. Dolayısıyla değeri tablo hücresinin text özelliğine yazıldı. O hücrede başka bir nesne olmadığı için sadece e.Item.Controls(1) diyerek o hücreye eriştik. Biraz önceki CustomerID örneğindeki gibi, OrderIDyi de siz kendinize kolay gelen bir yolla çekebilirsiniz.
Dropdownlistimiz artık kullanıma hazır. Hayırlı olsun..:)

TEMPLATE COLUMN KULLANARAK:
1-
Formun her prosedüründen erişilebilmesi için Global iki adet dataset (birisi Public, Html tarafından erişileceği için), iki adet dataadaptor ve bir tane de connection nesnesi tanımlayalım.

Dim Ds As New DataSet
Public Ds2 As New DataSet
Dim Con As New SqlConnection("Server=.;Database=Northwind;User ID=sa;Password=")
Dim daOrders As New SqlDataAdapter("select o.OrderID,o.CustomerID,c.CompanyName,o.ShipAddress from orders as o join Customers as c on c.CustomerID=o.CUstomerID ", Con)
Dim DaCustomers As New SqlDataAdapter("Select CustomerID,CompanyName from Customers", Con)

Burada Dsi Datagridimizi doldurmak için kullanacağız. Ds2yi ise Update anında Dropdownlistdeki mevcut kaydı seçmek için kullancağız.

2- DataGridimizi Property Builder kullanarak sütunlarını oluşturalım. Edit düğmesi,OrderID(boundcolumn),CompanyName (template column) ve ShipAdress(Bound Column) olarak sütunları, bu sırayla oluşturalım. HTML kodları:

<asp:DataGrid id="DataGrid1" runat="server" CellPadding="3" BackColor="White" BorderWidth="1px"
BorderStyle="None" BorderColor="#E7E7FF" GridLines="Horizontal" AutoGenerateColumns="False">
<SelectedItemStyle Font-Bold="True" ForeColor="#F7F7F7" BackColor="#738A9C"></SelectedItemStyle>
<AlternatingItemStyle BackColor="#F7F7F7"></AlternatingItemStyle>
<ItemStyle ForeColor="#4A3C8C" BackColor="#E7E7FF"></ItemStyle>
<HeaderStyle Font-Bold="True" ForeColor="#F7F7F7" BackColor="#4A3C8C"></HeaderStyle>
<FooterStyle ForeColor="#4A3C8C" BackColor="#B5C7DE"></FooterStyle>
<Columns>
<asp:EditCommandColumn ButtonType="PushButton" UpdateText="Update" CancelText="Cancel" EditText="Edit"></asp:EditCommandColumn>
<asp:BoundColumn DataField="OrderID" HeaderText="Sipariş ID"></asp:BoundColumn>
<asp:TemplateColumn HeaderText="M&#252;şteri Adı"> </asp:TemplateColumn>
<asp:BoundColumn DataField="ShipAddress" HeaderText="Sipariş Adresi"></asp:BoundColumn>
</Columns>
<PagerStyle HorizontalAlign="Right" ForeColor="#4A3C8C" BackColor="#E7E7FF" Mode="NumericPages"></PagerStyle>
</asp:DataGrid>

3- Page Load ekranına aşağıdaki kodları yazalım:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.DataGrid1.DataKeyField = "OrderID"
If Page.IsPostBack = True Then Exit Sub
daOrders.Fill(Ds)
Me.DataGrid1.DataSource = Ds
Me.DataGrid1.DataBind()
End Sub

Bu prsedür neredeyse birinci örnektekinin aynısı. Tek fark Me.DataGrid1.DataKeyField = "OrderID" satırı. Bunu,Update anında hangi satırın güncellenmesi gerktiğini öğrenmek için kullacağız. Yuarıdaki örnekte Datagridte bulunan bir sütundan çekmiştik değeri. Farklı olması açısından burada değişik bir şey denedim.

4- Şimdi Formun HTML tarafına geçip Template column altına şu satırları ekleyelim.

<asp:TemplateColumn HeaderText="Müşteri Adı">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem(), "CompanyName") %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="BenimDropdownlist" runat="server" DataValueField="CustomerID" DataTextField="CompanyName" DataSource="<%#Ds2%>" SelectedIndex=<%# DropDownListSec(Container.DataItem("CompanyName")) %> >
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateColumn>

Buradaki ItemTemplate tagi içine yazdığımız kodlar,Datagridimizdeki data satırlarının normal konumdaki görüntüsünü verir. Örneğimizde Datagridin bağlanan dataset tablosunun "CompanyName" alanının değerini ekrana işler. EditItemTemplate ise "Edit" düğmesine basıldıktan sonraki halini gösterir. Görüldüğü üzere Ds2ye bağlanıp ekrandaki değeri "CompanyName",Valuesı "CustomerID" bir DropDownList yaratılıyor. Seçili Indexini bulmak içinse CompanyName değeri gönderilip index değerinin geri döndüğü bir "DropDownListSec" fonksiyonu kullanılıyor.

5- DropDownListSec fonksiyonu:

Function DropDownListSec(ByVal CompanyName As String) As Integer
For x As Integer = 0 To Ds2.Tables(0).Rows.Count - 1
If CompanyName = Ds2.Tables(0).Rows(x).Item("CompanyName") Then
Return x
End If
Next
End Function

6-DataGridin EditCommand olayına yukarıdaki örnektekine benzer kodlar yazalım. Tek fark, "DropDownListSec" fonksiyonu kullanacağı için Ds2nin doldurulması...

Private Sub DataGrid1_EditCommand1(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles DataGrid1.EditCommand
Me.DataGrid1.EditItemIndex = e.Item.ItemIndex
Me.daOrders.Fill(Ds)
Me.DaCustomers.Fill(Ds2)
Me.DataGrid1.DataSource = Ds
Me.DataGrid1.DataBind()
End Sub

7-Düzenleme anında iptal tuşuna basıldığındaki kodlar:

Private Sub DataGrid1_CancelCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles DataGrid1.CancelCommand
Me.DataGrid1.EditItemIndex = -1
daOrders.Fill(Ds)
Me.DataGrid1.DataSource = Ds
DataGrid1.DataBind()
End Sub
End Class


8-
Ve son olarak DataGridin UpdateCommand olayının kodları var:

Private Sub DataGrid1_UpdateCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles DataGrid1.UpdateCommand
Dim BenimDropDown As DropDownList
BenimDropDown = e.Item.FindControl("BenimDropDownList")
Dim SiparisAdres As TextBox
SiparisAdres = e.Item.Controls(3).Controls(0)

Dim OrderID As String
OrderID = Me.DataGrid1.DataKeys(e.Item.ItemIndex)

Dim Sorgu As String
Sorgu = "Update Orders Set CustomerID=@CustomerID,ShipAddress=@ShipAddress where OrderID=@OrderID"
Dim com As New SqlCommand(Sorgu, Con)

com.Parameters.Add("@CustomerID", BenimDropDown.SelectedValue)
com.Parameters.Add("@ShipAddress", SiparisAdres.Text)
com.Parameters.Add("@OrderID", OrderID)
Con.Open()
com.ExecuteNonQuery()
Con.Close()

daOrders.Fill(Ds)
Me.DataGrid1.EditItemIndex = -1
Me.DataGrid1.DataSource = Ds
DataGrid1.DataBind()
End Sub

Eklediğimiz DropDownListi bulmak için bu sefer FindControls Methodunu kullandık. (HTML kısmında ID olarak "BenimDropDownList" atamıştık)

Dim BenimDropDown As DropDownList
BenimDropDown = e.Item.FindControl("BenimDropDownList")

Update yapmamız için gerekli OrderIDyi Page_Loadda DataKeyValue olarak atadığımız değerden çektiriyoruz.
Dim OrderID As String
OrderID = Me.DataGrid1.DataKeys(e.Item.ItemIndex)


Dropdownlistimiz artık kullanıma hazır. Hayırlı olsun..:)

SONUÇ:
Bu makalede DropDownListi Düzenleme anında nasıl DataGrid içinde kullanılacağını inceledik. Birincisi Datagridin ItemCreated ve ItemDataBound olaylarıyla, ikincisi de Template Column kullanarak.Fikir olması açısından Güncelleme için gerekli Primary Key değerini farklı yollardan elde ettik. DataGriddeki nesnelerin nasıl bulunacağı hakkında da fikir sahibi olduk.

Umarım yararlı bir makale olmuştur. Lütfen görüşlerinizi bildirin.

Örnek Kodları indirmek için tıklayınız.

Yalçın Uzun
yalcomania@hotmail.com