방법 1: BindingList와 INotifyPropertyChanged 조합 (권장)
public class InventoryItem : INotifyPropertyChanged
{
private string _itemName;
private double _itemValue;
public string ItemName
{
get => _itemName;
set { _itemName = value; OnPropertyChanged(); }
}
public double ItemValue
{
get => _itemValue;
set { _itemValue = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string prop = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}
public partial class InventoryView : Form
{
private BindingList<InventoryItem> _inventory = new();
private System.Timers.Timer _updateTimer = new(1500);
public InventoryView()
{
InitializeComponent();
itemGrid.DataSource = _inventory;
_updateTimer.Elapsed += UpdateItemValues;
_updateTimer.Start();
}
private void UpdateItemValues(object sender, ElapsedEventArgs e)
{
if (_inventory.Count == 0) return;
var rand = new Random();
foreach (var item in _inventory)
{
item.ItemValue *= 0.97 + rand.NextDouble() * 0.06;
}
}
private void AddNewItem(object sender, EventArgs e)
{
_inventory.Add(new InventoryItem
{
ItemName = $"Item {_inventory.Count + 1}",
ItemValue = new Random().Next(50, 500)
});
}
}
방법 2: DataTable을 이용한 데이터베이스 연동
public partial class SalesDashboard : Form
{
private DataTable _salesData = new DataTable("Sales");
private readonly System.Windows.Forms.Timer _dataTimer = new();
public SalesDashboard()
{
InitializeComponent();
_salesData.Columns.Add("ID", typeof(int));
_salesData.Columns.Add("Product", typeof(string));
_salesData.Columns.Add("Revenue", typeof(decimal));
salesGrid.DataSource = _salesData;
_dataTimer.Interval = 3000;
_dataTimer.Tick += RefreshSalesData;
_dataTimer.Start();
}
private void RefreshSalesData(object sender, EventArgs e)
{
if (_salesData.Rows.Count == 0) return;
var rand = new Random();
foreach (DataRow row in _salesData.Rows)
{
row["Revenue"] = (decimal)rand.Next(100, 5000);
}
}
}
방법 3: 수동 갱신 방식
public partial class ReportViewer : Form
{
private BindingSource _reportSource = new();
private List<ReportEntry> _reportData = new();
public ReportViewer()
{
InitializeComponent();
_reportSource.DataSource = _reportData;
reportGrid.DataSource = _reportSource;
}
private void ReloadData()
{
// 데이터 재로딩 로직
_reportSource.ResetBindings(false);
}
private void RefreshDisplay()
{
reportGrid.DataSource = null;
reportGrid.DataSource = _reportData;
}
}
핵심 구현 원리
- 자동 갱신 메커니즘:
- BindingList + INotifyPropertyChanged: 양방향 데이터 바인딩
- DataTable: 내장 변경 알림 시스템
- BindingSource.ResetBindings(): 수동 갱신 트리거
- 성능 개선 기법:
dataGridView.SuspendLayout();
// 대량 데이터 처리
dataGridView.ResumeLayout();
- 스레드 안전성 보장:
if (dataGrid.InvokeRequired)
{
dataGrid.Invoke(new Action(() => { /* UI 업데이트 */ }));
}
- 실시간 데이터베이스 연동:
SqlDependency.Start(connectionString);
SqlCommand cmd = new SqlCommand(query, conn);
SqlDependency dependency = new SqlDependency(cmd);
dependency.OnChange += (s, e) => LoadFreshData();
최적화 가이드라인
| 시나리오 | 권장 방식 |
| 객체 컬렉션 | BindingList + INotifyPropertyChanged |
| 데이터베이스 연동 | DataTable |
| 단순 데이터 표시 | 수동 갱신 |
성능 주의사항
// 대용량 데이터 처리
dataGridView.DoubleBuffered = true;
dataGridView.VirtualMode = true;