Skip to content

Instantly share code, notes, and snippets.

SortableBindingList 와 INotifyPropertyChanged 를 이용한 정렬가능한 양방항 binding DataGridView 만들기.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace INotifyPropertyChanged_SortableBindingList_test
{
public partial class Form1 : Form
{
List<Student> studentList = new List<Student>();
private BindingSource studentBindingSource = new BindingSource();
private SortableBindingList<Student> studentBindingList;
public Form1()
{
InitializeComponent();
studentList.Add(new Student("Tom", 17, 33.2, false));
studentList.Add(new Student("Sara", 19, 53.4, true));
studentList.Add(new Student("홍길동", 15, 130.2, false));
studentList.Add(new Student("이순신", 16, 43.2, true));
studentList.Add(new Student("Ace", 15, 23.2, false));
studentBindingList = new SortableBindingList<Student>(studentList);
studentBindingSource.DataSource = studentBindingList;
this.dataGridView1.DataSource = studentBindingSource;
}
private void Form1_Load(object sender, EventArgs e)
{
}
// 추가 버튼 click
private void button1_Click(object sender, EventArgs e)
{
studentBindingList.Add(new Student("유관순", 17, 45, false));
}
// 삭제 버튼 click
private void button2_Click(object sender, EventArgs e)
{
int rowIndex = this.dataGridView1.CurrentCell.RowIndex;
int columnIndex = this.dataGridView1.CurrentCell.ColumnIndex;
Debug.WriteLine($" 삭제될 cell ; row = {rowIndex}, column = {columnIndex}");
DataGridViewRow row = this.dataGridView1.Rows[rowIndex];
Student currentStudent = row.DataBoundItem as Student;
Debug.WriteLine($"-- 삭제될 student = Name={currentStudent.Name}, Weight={currentStudent.Weight}, 안경={currentStudent.Glass}");
this.dataGridView1.Rows.RemoveAt(rowIndex);
}
// Info 버튼 click
private void button3_Click(object sender, EventArgs e)
{
int rowIndex = this.dataGridView1.CurrentCell.RowIndex;
int columnIndex = this.dataGridView1.CurrentCell.ColumnIndex;
Debug.WriteLine($"current cell ; row = {rowIndex}, column = {columnIndex}");
//DataGridViewRow row = this.dataGridView1.SelectedRows[0];
DataGridViewRow row = this.dataGridView1.Rows[rowIndex];
Student currentStudent = row.DataBoundItem as Student;
if(currentStudent != null)
{
Debug.WriteLine($"총 student 수 = {this.studentBindingList.Count}");
for(int i=0; i<this.studentBindingList.Count; i++)
{
Debug.WriteLine($" student {i} = {this.studentBindingList[i].Name}, Weight={this.studentBindingList[i].Weight}");
}
Debug.WriteLine($"-- current student => {currentStudent.Name}, {currentStudent.Age}, {currentStudent.Weight}, 안경={currentStudent.Glass}");
}
}
// 변경 버튼 click
private void button4_Click(object sender, EventArgs e)
{
if(this.studentBindingList.Count > 0)
{
Student student = this.studentBindingList[0];
student.Weight += 1;
}
}
}
public class Student : INotifyPropertyChanged
{
private double _weight;
public string Name { get; set; }
public int Age { get; set; }
public double Weight
{
get
{
return _weight;
}
set
{
if (value != this._weight)
{
this._weight = value;
NotifyPropertyChanged();
}
}
}
public bool Glass { get; set; } = false; // 안경끼면, true
public event PropertyChangedEventHandler PropertyChanged;
public Student(string name, int age, double weight, bool glass)
{
this.Name = name;
this.Age = age;
this.Weight = weight;
this.Glass = glass;
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class SortableBindingList<T> : BindingList<T> where T : class
{
private bool _isSorted;
private ListSortDirection _sortDirection = ListSortDirection.Ascending;
private PropertyDescriptor _sortProperty;
public SortableBindingList()
{
}
public SortableBindingList(IList<T> list)
: base(list)
{
}
// Gets a value indicating whether the list supports sorting.
protected override bool SupportsSortingCore
{
get { return true; }
}
// Gets a value indicating whether the list is sorted.
protected override bool IsSortedCore
{
get { return _isSorted; }
}
// Gets the direction the list is sorted.
protected override ListSortDirection SortDirectionCore
{
get { return _sortDirection; }
}
// Gets the property descriptor that is used for sorting the list if sorting is implemented in a derived class; otherwise, returns null
protected override PropertyDescriptor SortPropertyCore
{
get { return _sortProperty; }
}
// Removes any sort applied with ApplySortCore if sorting is implemented
protected override void RemoveSortCore()
{
_sortDirection = ListSortDirection.Ascending;
_sortProperty = null;
_isSorted = false; //thanks Luca
}
// Sorts the items if overridden in a derived class
protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
_sortProperty = prop;
_sortDirection = direction;
List<T> list = Items as List<T>;
if (list == null) return;
list.Sort(Compare);
_isSorted = true;
//fire an event that the list has been changed.
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
private int Compare(T lhs, T rhs)
{
var result = OnComparison(lhs, rhs);
//invert if descending
if (_sortDirection == ListSortDirection.Descending)
result = -result;
return result;
}
private int OnComparison(T lhs, T rhs)
{
object lhsValue = lhs == null ? null : _sortProperty.GetValue(lhs);
object rhsValue = rhs == null ? null : _sortProperty.GetValue(rhs);
if (lhsValue == null)
{
return (rhsValue == null) ? 0 : -1; //nulls are equal
}
if (rhsValue == null)
{
return 1; //first has value, second doesn't
}
if (lhsValue is IComparable)
{
return ((IComparable)lhsValue).CompareTo(rhsValue);
}
if (lhsValue.Equals(rhsValue))
{
return 0; //both are the same
}
//not comparable, compare ToString
return lhsValue.ToString().CompareTo(rhsValue.ToString());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment