■ VirtualServerModeSource 클래스에서 데이터 테이블을 사용해 무한 스크롤을 처리하는 방법을 보여준다.
▶ CustomPropertyDescriptor.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
using System; using System.ComponentModel; using System.Data; namespace TestProject { /// <summary> /// 커스텀 속성 설명자 /// </summary> public class CustomPropertyDescriptor : PropertyDescriptor { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 속성 타입 /// </summary> private Type propertyType; /// <summary> /// 컴포넌트 타입 /// </summary> private Type componentType; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 속성 타입 - PropertyType /// <summary> /// 속성 타입 /// </summary> public override Type PropertyType { get { return this.propertyType; } } #endregion #region 컴포넌트 타입 - ComponentType /// <summary> /// 컴포넌트 타입 /// </summary> public override Type ComponentType { get { return this.componentType; } } #endregion #region 읽기 전용 여부 - IsReadOnly /// <summary> /// 읽기 전용 여부 /// </summary> public override bool IsReadOnly { get { return false; } } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Protected #region 생성자 - CustomPropertyDescriptor(propertyName, attributeArray) /// <summary> /// 생성자 /// </summary> /// <param name="propertyName">속성명</param> /// <param name="attributeArray">특성 배열</param> protected CustomPropertyDescriptor(string propertyName, Attribute[] attributeArray) : base(propertyName, attributeArray) { } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - CustomPropertyDescriptor(propertyName, propertyType, componentType) /// <summary> /// 생성자 /// </summary> /// <param name="propertyName">속성명</param> /// <param name="propertyType">속성 타입</param> /// <param name="componentType">컴포넌트 타입</param> public CustomPropertyDescriptor(string propertyName, Type propertyType, Type componentType) : this(propertyName, null) { this.propertyType = propertyType; this.componentType = componentType; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 값 리셋 가능 여부 구하기 - CanResetValue(component) /// <summary> /// 값 리셋 가능 여부 구하기 /// </summary> /// <param name="component">컴포넌트</param> /// <returns>값 리셋 가능 여부</returns> public override bool CanResetValue(object component) { return false; } #endregion #region 값 리셋하기 - ResetValue(component) /// <summary> /// 값 리셋하기 /// </summary> /// <param name="component">컴포넌트</param> public override void ResetValue(object component) { throw new NotImplementedException(); } #endregion #region 값 구하기 - GetValue(component) /// <summary> /// 값 구하기 /// </summary> /// <param name="component">컴포넌트</param> /// <returns>값</returns> public override object GetValue(object component) { DataRow dataRow = (DataRow)component; return dataRow[Name]; } #endregion #region 값 설정하기 - SetValue(component, value) /// <summary> /// 값 설정하기 /// </summary> /// <param name="component">컴포넌트</param> /// <param name="value">값</param> public override void SetValue(object component, object value) { DataRow dataRow = (DataRow)component; dataRow[Name] = value; } #endregion #region 값 직렬화 여부 구하기 - ShouldSerializeValue(component) /// <summary> /// 값 직렬화 여부 구하기 /// </summary> /// <param name="component">컴포넌트</param> /// <returns>값 직렬화 여부</returns> public override bool ShouldSerializeValue(object component) { return true; } #endregion } } |
▶ DataRowSource.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
using System.ComponentModel; using System.Data; namespace TestProject { /// <summary> /// 데이터 행 호스 /// </summary> public class DataRowSource : BindingList<DataRow>, ITypedList { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 데이터 테이블 /// </summary> private readonly DataTable dataTable; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - DataRowSource(dataTable) /// <summary> /// 생성자 /// </summary> /// <param name="dataTable">데이터 테이블</param> public DataRowSource(DataTable dataTable) { this.dataTable = dataTable; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 항목 속성 컬렉션 구하기 - GetItemProperties(sourceArray) /// <summary> /// 항목 속성 컬렉션 구하기 /// </summary> /// <param name="sourceArray">소스 배열</param> /// <returns>항목 속성 컬렉션</returns> public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] sourceArray) { if(this.dataTable == null) { return null; } PropertyDescriptor[] targetArray = new CustomPropertyDescriptor[this.dataTable.Columns.Count]; for(int i = 0; i < targetArray.Length; i++) { targetArray[i] = new CustomPropertyDescriptor ( this.dataTable.Columns[i].ColumnName, this.dataTable.Columns[i].DataType, typeof(DataRow) ); } PropertyDescriptorCollection targetCollection = new PropertyDescriptorCollection(targetArray); return targetCollection; } #endregion #region 리스트명 구하기 - GetListName(sourceArray) /// <summary> /// 리스트명 구하기 /// </summary> /// <param name="sourceArray">소스 배열</param> /// <returns>리스트명</returns> public string GetListName(PropertyDescriptor[] sourceArray) { return typeof(DataRow).Name; } #endregion } } |
▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
using System; using System.Data; using System.Threading.Tasks; using DevExpress.Data; using DevExpress.Utils; using DevExpress.XtraEditors; using DevExpress.XtraGrid.Views.Grid; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : XtraForm { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 배치 크기 /// </summary> private int batchSize = 10; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); this.gridView.InitializeView ( true, // Multi Select GridMultiSelectMode.CellSelect, // Grid Multi Select Mode DrawFocusRectStyle.CellFocus, // Draw Focus Rect Style true, // Show Indicator true, // Show Column Headers true, // Allow Column Moving true, // Allow Column Resizing true, // Allow Filter true, // Allow Sort false, // Allow Cell Merge EditorShowMode.Default, // Editor Show Mode false // Editable ); this.gridView.OptionsBehavior.AutoPopulateColumns = true; VirtualServerModeSource virtualServerModeSource = new VirtualServerModeSource(); virtualServerModeSource.MoreRows += virtualServerModeSource_MoreRows; virtualServerModeSource.AcquireInnerList += virtualServerModeSource_AcquireInnerList; this.gridControl.DataSource = virtualServerModeSource; this.gridView.BestFitColumns(); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 가상 서버 모드 소스 내부 리스트 획득시 처리하기 - virtualServerModeSource_AcquireInnerList(sender, e) /// <summary> /// 가상 서버 모드 소스 내부 리스트 획득시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void virtualServerModeSource_AcquireInnerList(object sender, VirtualServerModeAcquireInnerListEventArgs e) { DataTable sourceDataTable = GetDataTable(0, 0); e.InnerList = new DataRowSource(sourceDataTable); } #endregion #region 가상 서버 모드 소스 추가 행 처리하기 - virtualServerModeSource_MoreRows(sender, e) /// <summary> /// 가상 서버 모드 소스 추가 행 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void virtualServerModeSource_MoreRows(object sender, VirtualServerModeRowsEventArgs e) { e.RowsTask = Task.Factory.StartNew ( () => { DataTable batchDataTable = GetDataTable(e.CurrentRowCount, batchSize); DataRowSource dataRowSource = new DataRowSource(batchDataTable); for(int i = 0; i < batchDataTable.Rows.Count; i++) { dataRowSource.Add(batchDataTable.Rows[i]); } return new VirtualServerModeRowsTaskResult(dataRowSource, true); }, e.CancellationToken ); } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region 데이터 테이블 구하기 - GetDataTable(startID, count) /// <summary> /// 데이터 테이블 구하기 /// </summary> /// <param name="startID">시작 ID</param> /// <param name="count">카운트</param> /// <returns>데이터 테이블</returns> private DataTable GetDataTable(int startID, int count) { DataTable dataTable = new DataTable(); dataTable.Columns.Add("ID" , typeof(int )); dataTable.Columns.Add("Name" , typeof(string )); dataTable.Columns.Add("IsActive" , typeof(bool )); dataTable.Columns.Add("OrderCount" , typeof(int )); dataTable.Columns.Add("RegistrationDate", typeof(DateTime)); for(int i = startID; i < startID + count; i++) { dataTable.Rows.Add(i, "Name" + i, i % 2 == 0, i * 10, DateTime.Now.AddDays(i)); } return dataTable; } #endregion } } |