DataSource가 변경 될 때 DataGridView가 자동 스CROLING을 방지하려면 어떻게해야합니까?
-
19-09-2019 - |
문제
나는 이것을 시도했다 (http://brainof-dave.blogspot.com/2007/08/turning-for-auto-scrolling-bound.html) DataGridView의 데이터 소스 인 DataTable의 "RowChanged"이벤트에서는 소용이 없습니다.
기본적으로 BindingSource가 DataSource와 같은 DatagridView가 있습니다. BindingSource의 DataSource는 Datatable이 포함 된 Dataview입니다. 행 중 하나의 데이터가 변경 될 때마다 DataGridView는 다시 상단으로 스크롤됩니다. 이것에 대한 간단한 수정이 있습니까?
해결책
내가 찾은 것 같습니다. http://seewinapp.blogspot.com/2005/09/is-your-autoscroll-too-auto.html
나는 DataTable에서 Rowchanged 이벤트를 무시하고 FirstDisplayedScrollingRowIndex를 저장하고 해당 색인의 대의원 메소드를 인수로 호출 한 다음 FirstDisplayedScrollingRowIndex를 대표 방법 내부의 인수로 재설정했습니다. 모든 이벤트가 발사 될 때까지 자동 스크롤이 발생하지 않으므로 이벤트 내에서 해킹하려고 시도하는 것은 쓸모가 없습니다. 대의원은 이벤트 후에 호출되기 때문에 작동합니다.
다른 팁
다음은 데이터 소스를 변경 한 후 RowIndex를 복원하는 테스트 코드입니다. 이것은 또한 정렬 순서와 마지막 셀 위치를 복원합니다. 언어 : C# 7.0. 이것은 웹 검색의 도움과 함께 개인적으로 쓴 코드입니다.
private void UpdateDataSource()
{
SuspendLayout();
//Save last position and sort order
DataGridView g = DataGridView1;
Int32 idxFirstDisplayedScrollingRow = g.FirstDisplayedScrollingRowIndex;
SortOrder dgvLastSortDirection = g.SortOrder;
Int32 lastSortColumnPos = g.SortedColumn?.Index ?? -1;
Int32 dgvLastCellRow = g.CurrentCell?.RowIndex ?? -1;
Int32 dgvLastCellColumn = g.CurrentCell?.ColumnIndex ?? -1;
//Set new datasource
g.DataSource = myNewDataTableSource;
//Restore sort order, scroll row, and active cell
g.InvokeIfRequired( o =>
{
if(lastSortColumnPos > -1)
{
DataGridViewColumn newColumn = o.Columns[lastSortColumnPos];
switch(dgvLastSortDirection)
{
case SortOrder.Ascending:
o.Sort(newColumn, ListSortDirection.Ascending);
break;
case SortOrder.Descending:
o.Sort(newColumn, ListSortDirection.Descending);
break;
case SortOrder.None:
//No sort
break;
}
}
if(idxFirstDisplayedScrollingRow >= 0)
o.FirstDisplayedScrollingRowIndex = idxFirstDisplayedScrollingRow;
if(dgvLastCellRow>-1 && dgvLastCellColumn>-1)
o.CurrentCell = g[dgvLastCellColumn, dgvLastCellRow];
} );
ResumeLayout();
}
public static void InvokeIfRequired<T>(this T obj, InvokeIfRequiredDelegate<T> action) where T : ISynchronizeInvoke
{
if (obj.InvokeRequired)
{
obj.Invoke(action, new Object[] { obj });
}
else
{
action(obj);
}
}