|  | 
        
            | 
                    
                        | DataGridView Ile VirtualMode'da Çalışmak |  |  
                        | 
	
    
		
            | Gönderiliyor lütfen bekleyin... | 
 |  | 
        
            | Bu makalemde size DataGridView de VirtualMode da çalışmanın 
nasıl olduğundan bahsedeceğim. 
 Öncelikle buna neden ihtiyaç duyuyoruz veya nerde ihtiyaç duyacağız, bunu biraz 
açmak istiyorum. Veritabanı uygulamalarımızda çok sayıda veriyle uğraşmaktayız 
ve bunları bizim için en iyi şekilde gösterebilen tabii ki DataGridView 
kontrolüdür.
 
 DataGridView .Net Framework 2.0 gelen bir kontrol ve eskiden kullandığımız 
DataGrid in geliştirilmiş ve birçok özelliğin eklenmiş hali. Daha doğrusu bu 
kontrolle çalışmak çok daha esnek. Neyse konuyu dağıtmayalım. DataGridView de 
verilerimizi gösterirken muhakkak gridin sağ tarafında veya altında ya da her 
iki yerde birden ScrollBar larla karşılaşırız. Bu ScrollBar lar sayesinde 
verilerimiz arasında gezinti yapabiliyoruz.
 
 Bazen bu gezinme olayı hiç de kolay olmaz. Diyelimki elimizde 1000000 (bir 
milyon) satır gibi kayıt içeren veritabanında bir tablomuz var. Bu kadar veriyi 
DataGridView de gösterebiliriz fakat sistemimize göre bayağı bir performans 
kaybı yaşayacağız çünkü bu kadar veriyi bir seferde göstermek sistemimizdeki 
kaynakları çok tüketecektir. Ve görüceğiz ki veriler arasında dolaşmak hiç de 
kolay olmayacaktır.
 
 Gelin bunu bir örnek üstünde görelim ve neden VirtualMode da çalışmak daha 
avantajlı beraber göz atalım.
 
 Öncelikle yeni bir C# projesi oluşturup, bir DataGridView ve bir Button 
ekliyoruz.
 
 
 
   
 DataGridView 
nesnemizin Dock özelliğini Top olarak ayarladık. Nesnemizin ismini m_Data, 
Buttonumuzun ismini btnHucreSayisi olarak değiştirdik.
 
 VirtualMode da çalışmak için DataGridView nesnemizin VirtualMode özelliğini true 
yapmalıyız. Bunu dizayn ekranındaki özellikler bölümünden yapabileceğimiz gibi 
kod tarafında da atayabiliriz.
 
 Daha sonra kod ekranını açarak bir class oluşturuyoruz. Bu class DataGridView e 
ekliyeceğimiz veriler için bir şablon olucak ve bunun bir koleksiyonu yaparak 
1000000 kayıtı sağlıyacak bir yapı oluşturacağız.
 
 
 
  Veri kümemizi 
oluştururken Generics lerden yararlanacağız. İki veri kümesi oluşturarak biri 
bizim verilerimizi, diğeri gezilen satırları tutacak. 
    | class 
	DataObject //DataObject nesnemiz.... {
 
 private int m_Id;
 private int m_Val;
 
 public int Id
 {
 get { return m_Id; }
 set { m_Id = value; }
 }
 public int Val
 {
 get { return m_Val; }
 set { m_Val = value; }
 }
 }
 |  
 
 
   
    | private 
	List<DataObject> m_Data = new List<DataObject>(); private List<bool> m_Visited = new List<bool>();
 |  
 Şimdi değinmemiz 
gereken önemli bir nokta var. DataGridView de VirtualMode da çalışırken 
hücrelerin hepsi bir anda gride yüklenmez. Bunun yerine o anda ekranda 
gösterilenler grid de gösterilir. Yani kaydırma çubuklarıyla aşağı-yukarı veya 
sağa-sola yaptığımızda sadece durduğumuz anda ki hücreler gösterilecektir. Bu da 
bellekte çok miktarda verinin yer kaplamamasını sağlayarak performans 
sağlayacaktır. Aynı zamanda bu kadar kayıt arasında gezmek çok rahat olucaktır.
 
 Bu gösterim esnasında DataGridView de sadece VirtualMode da çalışırken meydana 
gelen bir olay tetiklenecektir. CellValueNeeded, bu olayı kullanarak 
verilerimizi DataGridView içersine yerleştireceğiz.
 
 Şimdi kodlarımızın tamamına bakarak ne yapmaya çalıştığımıza ve bize ne fayda 
sağlayacağına bakalım.
 
 
 
  Kodlardan da 
görüceğiniz gibi InitData() ve InitGrid() adında iki methot oluşturduk. 
Gridimize üç kolon ekleyerek bu kolonların isimlerini verdik. Esasında class 
ımızda veri olarak iki (m_Id,m_Val)alan gözükürken Gridimize üç kolon ekledik. 
Buradaki üçüncü kolondaki verileri başka türlü oluşturacağız ve burda karşımaza 
bir durum çıkacak. Bundan ilerleyen kısımda bahsedeceğim. InitGrid() kısmında 
gridimize m_Grid.Rows.Add(); satırıyla boş bir satır ekledik. Daha sonra bu 
satırın m_Grid.Rows.AddCopies(0, 1000000); satırıyla 1000000 kopyasını 
oluşturduk. 
    | using 
	System; using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.Text;
 using System.Windows.Forms;
 
 namespace DataGridView_Virtual_Mode
 {
 public partial class Form1 : Form
 {
 private List<DataObject> m_Data = new 
	List<DataObject>(); //Genericler List ye DataObject nesnesi gönderilerek 
	List artık DataObject tipinden nesneler alıyor..
 private List<bool> m_Visited = new 
	List<bool>(); // Genericler List ye "bool" gönderilerek List artık "bool" 
	tipinden nesneler alıyor..
 public Form1()
 {
 InitializeComponent();
 m_Grid.CellValueNeeded += new DataGridViewCellValueEventHandler(m_Grid_CellValueNeeded); 
	//Virtula Modda tetiklenecek CellValueNeeded olayı oluşturuluyor..
 InitData(); //Veriler nesnelerimize yükleyen metot ....
 InitGrid(); //Grid için gerekli işlemler.....
 }
 void m_Grid_CellValueNeeded(object 
	sender, DataGridViewCellValueEventArgs e)
 {
 // Bu olay 
	hangi hücre görütülenecekse onun için tetiklenir....e burda gerekli 
	değerleri tutuyor...
 m_Visited[e.RowIndex] 
	= true;
 if (e.ColumnIndex 
	== 0)
 {
 e.Value = m_Data[e.RowIndex].Id;
 }
 else if 
	(e.ColumnIndex == 1)
 {
 e.Value = m_Data[e.RowIndex].Val;
 }
 else if 
	(e.ColumnIndex == 2)
 {
 Random rnd = new Random();
 e.Value = rnd.Next(1, 10000000);
 }
 }
 private void InitData()
 {
 for (int 
	i = 0; i < 10000001; i++) //Döngüyle 1000000 tane DataObject nesnesi 
	oluşturuluyor ve m_Data Listesine ekleniyor...
 {
 m_Visited.Add(false); // m_Visited nesnesine 1000000 tane false ekleniyor..Bu 
	liste kaç satırı gezdiğimizi tutmak için...
 DataObject obj = new DataObject();
 obj.Id = i; //Değerler atanıyor...rasgele burda döngüdeki i değeri 
	kullanıldı....
 obj.Val = i * 2;
 m_Data.Add(obj);
 }
 }
 
 private void InitGrid() //Grid 
	işlemleri.....
 {
 m_Grid.ReadOnly = true;
 m_Grid.AllowUserToAddRows = false;
 m_Grid.AllowUserToDeleteRows = false;
 m_Grid.ColumnCount = 3; //Kaç kolon olacağı belirleniyor...
 m_Grid.Columns[0].Name = "Val 1"; //Kolonların isimleri veriliyor...
 m_Grid.Columns[1].Name = "Val 2";
 m_Grid.Columns[2].Name = "Val 3";
 m_Grid.Rows.Add(); //Boş bir satır DataGridView(ismi m_Grid) e ekleniyor...
 m_Grid.Rows.AddCopies(0, 1000000); //=. satırın 1000000 kopyası 
	oluşturuluyor....
 //m_Grid.DataSource 
	= m_Data; // Virtual mode aktif değilken dataların işlemesi
 }
 private void 
	btnHucreSayisi_Click(object sender, EventArgs e)
 {
 int 
	count = 0;
 
 for (int 
	i = 0; i < m_Visited.Count - 1; i++)
 {
 if (m_Visited[i])
 count++;
 }
 MessageBox.Show(count.ToString());
 }
 }
 
 class DataObject //DataObject nesnemiz....
 {
 
 private int m_Id;
 private int m_Val;
 
 public int Id
 {
 get { 
	return m_Id; }
 set { 
	m_Id = value; }
 }
 public int Val
 {
 get { return m_Val; }
 set { m_Val = value; }
 }
 }
 }
 |  
 InitData() kısmıyla da verileri oluşturuyoruz. Bu kısımda 1000000 kadar bir 
döngü açıp iki koleksiyonumuzu dolduruyoruz.
 
 m_Visited.Add(false); satırıyla daha herhangibir kayıt görüntelemediğimizden 
ziyaret edilen satırların hepsine false değeri atanıyor.
 
 Daha sonra DataObject nesneleri oluşturup bunların içideki değerler atanarak 
m_Data listemize şu satırlarla ekliyoruz.
 
 
 
   
    | DataObject 
	obj = new DataObject(); obj.Id = i;
 obj.Val = i * 2;
 m_Data.Add(obj);
 |  
 Şimdi uygulamamız 
çalıştırmaya hazır hale geldi. Önceden de bahsettiğim gibi VirtualMode da 
çalışırken CellValueNeeded olayı meydana gelir. Biz de bu olayda o anda 
görüntületmeye çalıştığımız hücrelerin değerlerini atayacağız.
 
 Bu olayda herhangi bir hücre görüntületmeye çalıştığımızda öncelikle o satırın 
görüntülendiğini bildiren satırı yazıyoruz.
 
 m_Visited[e.RowIndex] = true;
 
 Daha sonra bu 
olayda e parametresinden yararlanarak hangi kolonda ve satırda olduğumuzu yani 
hangi hücre de olduğumuzu bularak bu hücreye daha önce oluşturduğumuz listedeki 
verilerin satır numarasına göre atayacağız.
 
 
 
  Yukardaki 
satırlarda bişey dikkatinizi çekmiş olmalı. Son else if ifadesi içindeki 
satırlar. 
    | void 
	m_Grid_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) {
 if (e.ColumnIndex 
	== 0)
 {
 e.Value = m_Data[e.RowIndex].Id;
 }
 else if (e.ColumnIndex == 1)
 {
 e.Value = m_Data[e.RowIndex].Val;
 }
 else if (e.ColumnIndex == 2)
 {
 Random rnd = new Random();
 e.Value = rnd.Next(1, 10000000);
 }
 
 }
 
 
 |  
 
 
  Burada bir Random 
nesnesi (rnd) oluşturup bu nesnenin Next() metodu ile verilen aralıkta rastgele 
bir değer elde ediyoruz. Bu değeri son sutunumuzdaki hücrelere eşitliyoruz. 
    | Random 
	rnd = new Random(); e.Value = rnd.Next(1, 10000000);
 
 
 |  
 CellValueNeeded olayı kaydırma çubuklarını hareket ettirip hücreleri 
görüntülemeye çalıştıtğımızda da meydana gelir.
 
 En son olarak btnHucreSayisi adlı button umuzun Click olayındaki kodlara göz 
atalım. Burada gezilen satırlar birer birer sayılarak kaç satır olduğu ekrana 
MessageBox ile gösterilecektir. Programı çalıştırıp kaydırma çubuklarını en sona 
kadar hareket ettirdiğimizde göreceğiz ki 1000000 tane satır gezilmemiş.
 
 Şimdi programımız çalıştıralım ve genel görünüme bakalım:
 
 
  
 
 Şimdi kaydırma çubuğunu en aşağı kadar indirelim ve “Hücre Sayısı” yazan 
button a tıklayalım. Şu şekilde bir ekranla karşılaşacağız:
 
 
  
 Gördüğünüz gibi 
MessageBox ile gezilen yani görüntülenmeye çalışılan satır sayısını öğrendik. 
Son kaydımızda 1000000 gibi bir sayı yazmasına (0 dan başladığımız için 1000001. 
kayıt) rağmen bize gelen bilgi 197 gibi bir sayı (kaydırma hızınıza bağlı olarak 
değişir).
 
 Burdan da anlaşılacağı gibi DataGridView de VirtualMode da çalışırken griddeki 
veriler sadece görüntülenmek istendiği zaman ekranda görüntülenir. Diğer 
satırlardaki veriler yoktur. Ne zaman kaydırma çubuğunu hareket ettirsek 
CellValueNeeded olayı meydana gelicek ve hücrelerdeki değerler gözükecektir. Biz 
de burada hücrelerdeki değerleri hesaplamak bu olayda yazdık.
 
 Şimdi, eğer biz bu gridle VirtualMode çalışmamış olsaydık ne farkedicekti ? 
Öncelikle programınızı çalıştırdığınızda bir süre bekliyeceksiniz çünkü gridde 
büyük miktarda bir satır eklenecek ve bu satırlar için değerler oluşturalacaktır. 
Eğer VirtualMode da çalışmadan bir seferde bu değeri göstermeye çalışırsak ne 
kadar bekliyecektik ve veriler arasında nasıl bir gezinme rahatlığı olucaktı.
 
 Bunun için DataGridView kontrolümüzün özelliklerinden VirtualMode özelliğini 
false yapıcağız. Daha sonra InitGrid() metodundaki son açıklama satırına kadar 
olan satırları inaktif etmek için açıklama satırı yapıp son açıklama satırını 
aktif yapın. Yani InitGrid() metodumuzda sadece aşağıdaki satır aktif olucak:
 
 m_Grid.DataSource = m_Data;
 
 Bu satırla m_Data 
koleksiyonumuzdaki verileri DataGridView e bind ettik ve bir seferde verileri 
göstermeye çalıştık.
 
 Programızı çalıştıralım bakalım ne kadar bekliyeceğiz. Sisteminize bağlı olarak 
bu bekleme süresi değişecektir fakat şurda bir gerçek var ki ilk duruma göre çok 
daha uzun bekledik ve kaydırma çubuğuyla satırlar arasında hiç de rahat 
gezemedik.
 İsterseniz şimdiki durumla ilk durum arasındaki hızı karşılaştırmak için zaman 
tutabilirsiniz.
 Ben kendi sistemimde her iki durumdaki elde ettiğim zamanlar arsında
 şöle bir sonuç çıktı:
 
 VirtualMode durumunda :11 sn
 Normal durumda              
:1 dk 6 sn
 
 Bu değerler 
program Debug edilmeye başladığından itibaren geçen sürelerdir. Gördüğünüz gibi 
iki durum arasında ne kadar önemli bir fark var. Ve satırlar arasında hiç de 
rahat gezinti olmadı. Sisteminize bağlı olarak bu değerler değişebilir. Fakat şu 
bir gerçek ki iki durum arasında performans olarak gözle gözükür bir fark olduğu....
 
 Son olarak CellValueNeeded olayından biraz bahsetmek istiyorum. Programımızı ilk 
çalıştırdığımızda DataGridView deki değerlerden en son kolondaki hücrelere 
fareyle tıkladığımızda verilerin değiştiğini görüceksiniz. Peki neden böyle 
bişey oldu ?
 
 Biz CellValueNeeded olayında son else if bloğunda restgele değerler oluşturarak 
bu değerleri son kolona atamıştık. Hücrelere tıkladığımız anda CellValueNeeded 
olayı tekrar tetiklenir bu yüzden yeniden rastgele bir değer hesaplanıcağından 
bu değerler değişecektir. Diğer kolonlarda böle bir durum olmayacaktır çünkü bu 
hücreler için değerleri baştan belirlemiştik. Fakat hücreler tıkladığımızda, bu 
hücrelerde de CellValueNeeded olayı tetiklenir.
 
 Burada makeleme son verirken umut ediyorum okuyanlar için faydalı olur. Tekrar 
buluşmak dileğiyle...
 
 Recep DABAN
 
 Mail: [email protected]
 
 
                Makale:DataGridView Ile VirtualMode'da Çalışmak C#, Visual C# ve .NET Recep  Daban
 | 
        
            |  | 
        
            |  | 
        
            | 
                    
                        
                            
                        
                            Eklenen Son 10 
                            Bu Konuda Geçmiş 10 
                        
                            Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
                         
                            Son Eklenen 10 Makale Yükleniyor
                         
                            Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
                         | 
        
            |  |