星期一, 8月 07, 2023

[C#] DataGridView 綁定自訂型別

社群內看到的問題,希望在 DataGridView 上可以直接綁定自定型別,自訂型別示意如下
public class Person
{
    public string Name { get; set; }

    public Address Address { get; set; }
}

public class Address
{
    public string City { get; set; }
}
重點放在 Addresss class 能否直接綁定在 DataGridView 上,透過 DataGridView.CellFormatting event 來做到,Code 如下
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace DGVDataBinding
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private DataGridViewTextBoxColumn _colCity { get; set; }

        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.AutoGenerateColumns = false;

            ColumnInit();
            
            SetDataSource();

            dataGridView1.CellFormatting += DataGridView1_CellFormatting;
        }

        private void ColumnInit()
        {
            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn()
            {
                HeaderText = "姓名",
                DataPropertyName = nameof(Member.Name),
            });

            _colCity = new DataGridViewTextBoxColumn()
            {
                HeaderText = "都市",
                // 直接綁定 Address Class
                DataPropertyName = nameof(Address),
            };
            dataGridView1.Columns.Add(_colCity);
        }

        private void SetDataSource()
        {
            List<Member> source = new List<Member>();
            source.Add(new Member()
            {
                Name = "名字 1",
                Address = new Address() { City = "台北" }
            });
            source.Add(new Member()
            {
                Name = "名字 2",
                Address = new Address() { City = "高雄" }
            });

            dataGridView1.DataSource = source;
        }

        private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (e.ColumnIndex == _colCity.Index)
            {
                // DataPropertyName 設定為 Address,判斷是否可以轉為 Class
                // 可以轉為 class 後,把 City 欄位資料塞回去            
                if (e.Value is Address a)
                    e.Value = a.City;
            }
        }
    }

    public class Member
    {
        public string Name { get; set; }

        public Address Address { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
    }
}


另外有大神也分享在 RowAdded event 內顯示 Address 方式,雖然事件不同,但基本上原理都是相同的,把資料塞回去就是

沒有留言:

張貼留言