Created
November 28, 2019 07:18
SortableBindingList 와 INotifyPropertyChanged 를 이용한 정렬가능한 양방항 binding DataGridView 만들기.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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