在.NET Compact Framework中,DataGrid控件并不支持像ListView或ListBox那样的手指滑动滚动功能。这可能会让人感到惊讶,因为通常情况下,如果需要这样的功能,可能会选择使用ListView控件。然而,在一个项目中,需要在DataGrid上实现这个功能,因为已经对网格进行了大量自定义,所以无法回到ListView。本以为可以很容易地为网格添加这个功能,做到了,这并不难。但问题是没有办法设置原生滚动条的位置。所以有一个在手指滑动时滚动的网格,但滚动条的位置没有变化。由于无法通过程序设置滚动条位置,需要“隐藏”滚动条。这就是这个滚动条控件的原因。
使用这个控件的代码非常简单。目前,这个控件没有无参数的构造函数,所以不能进行拖放操作。但它真正需要的只是一个DataGrid实例和DataGrid的数据源。
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = GetData();
var scrollBar = new GridVScrollBar(this.dataGrid1, dt);
// 如果不需要显示滚动条,这行代码就不需要
this.Controls.Add(scrollBar);
}
限制:目前,第二个输入参数需要是DataTable或IList类型。认为通过一些额外的代码,可以使其成为DataTable和IEnumerable。
private void SetVisibleItems(int startIndex)
{
object displaySource = new object();
var endIndex = VisibleRowCount + startIndex;
if (_controlDataSource is DataTable)
{
var sdt = _controlDataSource as DataTable;
var dt = sdt.Clone();
for (int i = startIndex; i < endIndex; i++)
{
if (i < ItemCount && i >= 0)
{
dt.Rows.Add(sdt.Rows[i].ItemArray);
}
}
displaySource = dt;
}
else if (_controlDataSource is IList)
{
var sdt = _controlDataSource as IList;
var list = (IList)Activator.CreateInstance(_controlDataSource.GetType());
for (int i = startIndex; i < endIndex; i++)
{
list.Add(sdt[i]);
}
}
_dataGrid.DataSource = displaySource;
_dataGrid.Select(0);
// 或者可以在这里引发一个事件,如DisplaySourceReady,以便在网格刷新之前处理任何额外的事情
_dataGrid.Refresh();
}
应该为那些相对于行高有较小可见窗口的网格设置EnableAutoScroll为false。因为自动滚动逻辑工作得不是很好,这种情况还没有出现。
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = GetData();
var scrollBar = new GridVScrollBar(this.dataGrid1, dt);
scrollBar.EnableAutoScroll = false;
this.Controls.Add(scrollBar);
}