9 Kasım 2012 Cuma

C# ile Düzenlenebilir ListView Oluşturma

 Merhaba Webkolog okurları,

Bugün sizlere, C# .NET Framework 4 ve Microsoft Visual Studio 2010 kullanarak, nasıl düzenlenebilir bir ListView oluşturacağınızı anlatacağım. ListView kontrolü, verileri satır ve sütunlar halinde görüntülemek için sıkça kullanılır. Bu makalede, bu kontrolü kullanarak kullanıcıların doğrudan hücreler üzerinde değişiklik yapabileceği bir yapı oluşturacağız.

Düzenlenebilir ListView Nedir?

Düzenlenebilir bir ListView, kullanıcıların içindeki verilere doğrudan müdahale edebildiği bir kontrol anlamına gelir. Kullanıcılar bir hücreye tıkladığında, o hücre bir metin kutusu veya açılır liste gibi bir düzenleme kontrolüne dönüşür ve kullanıcı veriyi değiştirebilir.

C# ile Düzenlenebilir ListView Oluşturma

Aşağıdaki adımları izleyerek, düzenlenebilir bir ListView oluşturabilirsiniz:

  1. Yeni Bir Sınıf Oluşturun: ListViewEx adında, ListView sınıfından türeyen yeni bir sınıf oluşturun. Bu sınıf, düzenleme işlevselliğini ekleyeceğimiz yer olacak.
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace Webkolog
    {
        public class ListViewEx : ListView
        {
            // Gerekli Win32 API tanımları ve değişkenler buraya gelecek
        }
    }
    
  2. Win32 API Fonksiyonlarını Tanımlayın: LVM_GETSUBITEMRECT mesajını göndermek için user32.dll içindeki SendMessage fonksiyonunu kullanmamız gerekiyor. Bu mesaj, bir alt öğenin (subitem) dikdörtgen alanını almak için kullanılır. Ayrıca, hücrenin konumunu ve boyutunu elde etmek için bir RECT yapısı tanımlayacağız.
    [StructLayout(LayoutKind.Sequential)]
    internal struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }
    
    internal class Win32
    {
        public const int LVM_GETSUBITEMRECT = (0x1000) + 56;
        public const int LVIR_BOUNDS = 0;
    
    [DllImport("user32.dll", SetLastError = true)]
        public static extern int SendMessage(IntPtr hWnd, int messageID, int wParam, ref RECT lParam);
    }
    
  3. Gerekli Değişkenleri ve Kontrolleri Ekleyin: Düzenleme sırasında kullanılacak TextBox ve ComboBox kontrollerini, ayrıca hücre bilgilerini ve diğer yardımcı değişkenleri sınıfımıza ekleyelim.
    private TextBox textBox = new TextBox();
    private ComboBox combo = new ComboBox();
    private int editingRow = -1;
    private int editingCol = -1;
    private bool mouseDown = false;
    private Hashtable customCells = new Hashtable();
    private bool addSubItem = false;
     public bool AddSubItem
        {
            set
            {
                this.addSubItem = value;
            }
        }
    private bool hideComboAfterSelChange = false;
        public bool HideComboAfterSelChange
        {
            set
            {
                this.hideComboAfterSelChange = value;
            }
        }
    
  4. Kurucu Metodu ve InitializeComponent Metodunu Oluşturun: Bu metotlar içinde, metin kutusu ve açılır liste kontrollerini oluşturup, gerekli olayları atayacağız.
    public ListViewEx()
    {
        InitializeComponent();
    }
    
    private void InitializeComponent()
    {
        textBox.Visible = false;
        textBox.BorderStyle = BorderStyle.FixedSingle;
        textBox.Leave += new EventHandler(textBox_Leave);
    
    combo.Visible = false;
        Controls.Add(textBox);
        Controls.Add(combo);
        combo.DropDownStyle = ComboBoxStyle.DropDownList;
        combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged);
    }
    
  5. GetSubItemRect Metodunu Oluşturun: Bu metot, tıklanan hücrenin konumunu ve boyutunu almak için LVM_GETSUBITEMRECT mesajını gönderir.
    private RECT GetSubItemRect(Point clickPoint)
    {
        RECT subItemRect = new RECT();
        editingRow = editingCol = -1;
    
    ListViewItem item = GetItemAt(clickPoint.X, clickPoint.Y);
        if (item != null)
        {
            for (int index = 0; index < Columns.Count; index++)
            {
                subItemRect.top = index + 1;
                subItemRect.left = Win32.LVIR_BOUNDS;
                int result = Win32.SendMessage(Handle, Win32.LVM_GETSUBITEMRECT, item.Index, ref subItemRect);
                if (result != 0)
                {
                    if (clickPoint.X < subItemRect.left)
                    {
                        editingRow = item.Index;
                        editingCol = 0;
                        break;
                    }
                    if (clickPoint.X >= subItemRect.left && clickPoint.X <= subItemRect.right)
                    {
                        editingRow = item.Index;
                        editingCol = index + 1;
                        break;
                    }
                }
            }
        }
        return subItemRect;
    }
    
  6. AddEditableCell ve AddComboBoxCell Metotlarını Oluşturun: Bu metotlar, hangi hücrelerin düzenlenebilir olacağını veya hangi hücrelerde açılır liste gösterileceğini belirtmek için kullanılır.
     
    1.	public void AddEditableCell(int row, int col)
        {
            customCells[new SubItem(row, col)] = null;
        }
    
    public void AddComboBoxCell(int row, int col, StringCollection data)
        {
            customCells[new SubItem(row, col)] = data;
        }
    
    public void AddComboBoxCell(int row, int col, string[] data)
        {
            StringCollection param = new StringCollection();
            param.AddRange(data);
            AddComboBoxCell(row, col, param);
        }
    
    internal class SubItem
        {
            public readonly int row;
            public readonly int col;
    
    public SubItem(int row, int col)
            {
                this.row = row;
                this.col = col;
            }
        }
    
  7. ShowTextBox ve ShowComboBox Metotlarını Oluşturun: Bu metotlar, düzenleme kontrolünü (metin kutusu veya açılır liste) hücrenin üzerinde görüntüler.
    1.	 private void ShowTextBox(Point location, Size size)
        {
            textBox.Size = size;
            textBox.Location = location;
            textBox.Text = Items[editingRow].SubItems[editingCol].Text;
            textBox.Show();
            textBox.Focus();
        }
    
    private void ShowComboBox(Point location, Size size, StringCollection data)
        {
            combo.Size = size;
            combo.Location = location;
            combo.Items.Clear();
            foreach (string text in data)
            {
                combo.Items.Add(text);
            }
            combo.Text = Items[editingRow].SubItems[editingCol].Text;
            combo.DropDownWidth = GetDropDownWidth(data);
            combo.Show();
        }
         private int GetDropDownWidth(StringCollection data)
        {
            if (data.Count == 0)
            {
                return combo.Width;
            }
            string maximum = data[0];
            foreach (string text in data)
            {
                if (maximum.Length < text.Length)
                {
                    maximum = text;
                }
            }
            return (int)(CreateGraphics().MeasureString(maximum, Font).Width);
        }
    
  8. OnMouseUp Metodunu Override Edin: Bu metot, kullanıcı hücreye tıkladığında tetiklenir. Burada, tıklanan hücrenin düzenlenebilir olup olmadığını kontrol edip, uygun düzenleme kontrolünü görüntüleriz.
    1.	 protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            try
            {
                textBox.Visible = combo.Visible = false;
                if (!mouseDown)
                {
                    return;
                }
                if (!FullRowSelect || View != View.Details)
                {
                    return;
                }
                mouseDown = false;
                RECT rect = GetSubItemRect(new Point(e.X, e.Y));
                if (editingRow != -1 && editingCol != -1)
                {
                    SubItem cell = GetKey(new SubItem(editingRow, editingCol));
                    if (cell != null)
                    {
                        Size size = new Size(Columns[editingCol].Width, Items[editingRow].Bounds.Height);
                        Point location = editingCol == 0 ? new Point(0, rect.top) : new Point(rect.left, rect.top);
                        ValidateAndAddSubItems();
                        if (customCells[cell] == null)
                        {
                            ShowTextBox(location, size);
                        }
                        else
                        {
                            ShowComboBox(location, size, (StringCollection)customCells[cell]);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.ToString());
            }
        }
    
    private void ValidateAndAddSubItems()
        {
            try
            {
                while (Items[editingRow].SubItems.Count < Columns.Count && addSubItem)
                {
                    Items[editingRow].SubItems.Add("");
                }
            }
            catch (Exception ex)
            {
                 System.Diagnostics.Trace.WriteLine(ex.ToString());
            }
        }
    
    private SubItem GetKey(SubItem cell)
        {
            try
            {
                foreach (SubItem key in customCells.Keys)
                {
                    if (key.row == cell.row && key.col == cell.col)
                    {
                        return key;
                    }
                    else if (key.row == -1 && key.col == cell.col)
                    {
                        return key;
                    }
                    else if (key.row == cell.row && key.col == -1)
                    {
                        return key;
                    }
                    else if (key.row == -1 && key.col == -1)
                    {
                        return key;
                    }
                }
            }
            catch (Exception ex)
            {
                 System.Diagnostics.Trace.WriteLine(ex.ToString());
            }
            return null;
        }
    
  9. OnMouseDown Metodunu Override Edin: Bu metot, kullanıcı ListView içinde bir yere tıkladığında tetiklenir. Burada, düzenleme kontrollerini gizleyeceğiz.
    1.	protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            try
            {
                mouseDown = true;
                textBox.Hide();
                combo.Hide();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.ToString());
            }
        }
    
  10. textBox_Leave ve combo_SelectedIndexChanged Olaylarını Oluşturun: Bu olaylar, kullanıcı metin kutusundan ayrıldığında veya açılır listeden bir seçim yaptığında tetiklenir. Burada, yeni değeri hücreye kaydedeceğiz.
    1.	private void textBox_Leave(object sender, EventArgs e)
        {
            try
            {
                if (editingRow != -1 && editingCol != -1)
                {
                    Items[editingRow].SubItems[editingCol].Text = textBox.Text;
                    textBox.Hide();
                }
            }
            catch (Exception ex)
            {
                 System.Diagnostics.Trace.WriteLine(ex.ToString());
            }
        }
    
    private void combo_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (editingRow != -1 && editingCol != -1)
                {
                    Items[editingRow].SubItems[editingCol].Text = combo.Text;
                    combo.Visible = !hideComboAfterSelChange;
                }
            }
            catch (Exception ex)
            {
                 System.Diagnostics.Trace.WriteLine(ex.ToString());
            }
        }
    

Nasıl Kullanılır?

  1. ListViewEx sınıfının bir örneğini oluşturun.
  2. View özelliğini View.Details olarak ayarlayın ve sütunlar ekleyin.
  3. AddEditableCell veya AddComboBoxCell metotlarını kullanarak, hangi hücrelerin düzenlenebilir olacağını belirtin.
  4. ListView'e öğeler ekleyin.
    1.	ListViewEx listViewEx = new ListViewEx();
    listViewEx.View = View.Details;
    listViewEx.Columns.Add("Ad", 100);
    listViewEx.Columns.Add("Soyad", 100);
    listViewEx.Columns.Add("Not", 100);
    listViewEx.AddEditableCell(-1, 0); // Tüm satırlardaki ilk sütun düzenlenebilir
    listViewEx.AddEditableCell(-1, 1);
     StringCollection grades = new StringCollection();
                grades.AddRange(new string[] { "A", "B", "C", "D", "E" });
    listViewEx.AddComboBoxCell(-1, 2, grades);
    
    listViewEx.Items.Add(new ListViewItem(new string[] { "Ahmet", "Yılmaz", "A" }));
    listViewEx.Items.Add(new ListViewItem(new string[] { "Ayşe", "Demir", "B" }));
    

Bu adımları tamamladıktan sonra, kullanıcıların ListView içindeki hücrelere tıklayarak verileri düzenleyebildiğini göreceksiniz. Bu, özellikle kullanıcıların uygulama içinde veri girişi yapması gereken durumlarda oldukça kullanışlıdır.

Webkolog'u takipte kalın!

Hepinize bol kodlu ve başarılı projeler dilerim!

0 yorum:

Yorum Gönder