最开始的情况:
希望的效果:
方法1:我修改了DataGrid的样式,是可以达到目的,不过要配好外面的DataPager来确定位置,如果DataPager的宽度改变了,那么就需要手动再去修改Style里滚动条位置(不过一般情况也不会去修改~)。
方法2:在外面创建一个ScrollBar然后通过这个滚动条来控制表格的滚动。
想到了绑定,不过直接在DataGrid的属性里貌似找不到他的滚动条。搜到个函数可以找到对象,但是在前台和后台都尝试绑定却依旧控制不了(拖动DataGrid的滚动条,外置的会跟着动),于是再搜索,终于在一个的网友的文章里找到了同样的问题,不过他写的好简略而且没有给出源代码。我来补充吧。
用于获得和同步Scroll的扩展类:
DataGridScrollExtensions
public static class DataGridScrollExtensions
{
/// <summary>
/// 枚举,横向滚动条/纵向滚动条
/// </summary>
public enum ScrollMode
{
Vertical,
Horizontal
}
/// <summary>
/// 把滚动条至于最前端。
/// <param name="mode"></param>
public static void ScrollToStart(this DataGrid grid, ScrollMode mode)
{
switch (mode)
{
case ScrollMode.Vertical:
grid.ScrollToPercent(ScrollMode.Vertical, 0);
break;
case ScrollMode.Horizontal:
grid.ScrollToPercent(ScrollMode.Horizontal, 0);
break;
}
}
/// <summary>
/// 把滚动条至于最后端。
/// </summary>
/// <param name="mode"></param>
public static void ScrollToEnd(this DataGrid grid, ScrollMode mode)
{
switch (mode)
{
case ScrollMode.Vertical:
grid.ScrollToPercent(ScrollMode.Vertical, 100);
break;
case ScrollMode.Horizontal:
grid.ScrollToPercent(ScrollMode.Horizontal, 100);
break;
}
}
/// <summary>
/// 把滚动条至于指定位置。
/// </summary>
/// <param name="mode"></param>
/// <param name="percent"></param>
public static void ScrollToPercent(this DataGrid grid, ScrollMode mode, double percent)
{
if (percent < 0)
percent = 0;
else if (percent > 100)
percent = 100;
var scrollProvider = GetScrollProvider(grid);
//滚动
switch (mode)
{
case ScrollMode.Vertical:
scrollProvider.SetScrollPercent(System.Windows.Automation.ScrollPatternIdentifiers.NoScroll, percent);
break;
case ScrollMode.Horizontal:
scrollProvider.SetScrollPercent(percent, System.Windows.Automation.ScrollPatternIdentifiers.NoScroll);
break;
}
}
/// <summary>
/// 获取滚动条当前位置。
/// </summary>
/// <param name="mode"></param>
/// <returns></returns>
public static double GetScrollPosition(this DataGrid grid, ScrollMode mode)
{
var scrollBar = grid.GetScrollbar(mode);
return scrollBar.Value;
}
/// <summary>
/// 获取滚动条最大值。
/// </summary>
/// <param name="mode"></param>
/// <returns></returns>
public static double GetScrollMaximum(this DataGrid grid, ScrollMode mode)
{
var scrollBar = grid.GetScrollbar(mode);
return scrollBar.Maximum;
}
/// <summary>
/// 设置滚动条到指定位置。
/// </summary>
/// <param name="mode"></param>
/// <param name="position"></param>
public static void Scroll(this DataGrid grid, ScrollMode mode, double position)
{
var scrollBar = grid.GetScrollbar(mode);
double positionPct = ((position / scrollBar.Maximum) * 100);
grid.ScrollToPercent(mode, positionPct);
}
/// <summary>
/// 获取滚动条。
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
private static IScrollProvider GetScrollProvider(DataGrid grid)
{
var p = FrameworkElementAutomationPeer.FromElement(grid) ?? FrameworkElementAutomationPeer.CreatePeerForElement(grid);
return p.GetPattern(PatternInterface.Scroll) as IScrollProvider;
}
/// <summary>
/// 在指定的DataGrid中指定需要找到的滚动条(横/纵)。
/// </summary>
/// <param name="grid"></param>
/// <param name="mode"></param>
/// <returns></returns>
public static ScrollBar GetScrollbar(this DataGrid grid, ScrollMode mode)
{
if (mode == ScrollMode.Vertical)
return grid.GetScrollbar("VerticalScrollbar");
else
return grid.GetScrollbar("HorizontalScrollbar");
}
/// <summary>
/// 在指定的DataGrid中找到他的Scroll。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dep"></param>
/// <returns></returns>
private static ScrollBar GetScrollbar(this DependencyObject dep, string name)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dep); i++)
{
var child = VisualTreeHelper.GetChild(dep, i);
if (child != null && child is ScrollBar && ((ScrollBar)child).Name == name)
return child as ScrollBar;
else
{
ScrollBar sub = GetScrollbar(child, name);
if (sub != null)
return sub;
}
}
return null;
}
}
前台Xaml:
<toolkit:DockPanel >
<toolkit:DockPanel toolkit:DockPanel.Dock="Bottom" Height="26">
<sdk:DataPager x:Name="dataPager" PageSize="13" Width="173" FontFamily="Tahoma" toolkit:DockPanel.Dock="Right"/>
<ScrollBar x:Name="scorllBar1" Height="24" Orientation="Horizontal" ViewportSize="10"/>
</toolkit:DockPanel>
<sdk:DataGrid x:Name="dataGrid"
AutoGenerateColumns="False" IsReadOnly="True"
AlternatingRowBackground="AntiqueWhite"
Background="#FFE0DEDE" toolkit:DockPanel.Dock="Top">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="机构" Binding="{Binding JG}"/>
<sdk:DataGridTextColumn Header="办理柜员" Binding="{Binding BLGY}"/>
<sdk:DataGridTextColumn Header="业务" Binding="{Binding YW}"/>
<sdk:DataGridTextColumn Header="票号" Binding="{Binding PH}"/>
<sdk:DataGridTextColumn Header="到达时间" Binding="{Binding DDSJ}"/>
<sdk:DataGridTextColumn Header="办理时间" Binding="{Binding BLSJ}"/>
<sdk:DataGridTextColumn Header="结束时间" Binding="{Binding JSSJ}"/>
<sdk:DataGridTextColumn Header="等待时长" Binding="{Binding DDSC}"/>
<sdk:DataGridTextColumn Header="服务时长" Binding="{Binding FWSC}"/>
<sdk:DataGridTextColumn Header="驻留时长" Binding="{Binding ZLSC}"/>
<sdk:DataGridTextColumn Header="业务状态" Binding="{Binding YWZT}"/>
<sdk:DataGridTextColumn Header="评价" Binding="{Binding PJ}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</toolkit:DockPanel>
PS:DockPanel是属于Silverlight Toolkit的控件,
确认你安装了Silverlight Toolkit.再引用System.windows.control。
后台CS:
1、设置DataPager
PagedCollectionView itemListView = new PagedCollectionView(new dataSourceList());
dataGrid.ItemsSource = itemListView;
dataPager.Source = itemListView;
PS:dataSourceList是DateGrid的数据源,我前面有写http://blog.csdn.net/wushang923/article/details/7168820
2、设置ScrollBar
/// <summary>
/// 尝试通过VistualTree来找到Scrollbar对象
/// </summary>
private void TryUseVisualTree()
{
EventHandler h = null;
ScrollBar scroll = null;
//在LayoutUpated里操作能确保数据加载完成,这样下面的设置才不会出错。
dataGrid.LayoutUpdated += h = delegate
{
if (scroll == null)
{
scroll = DataGridScrollExtensions.GetScrollbar(dataGrid, DataGridScrollExtensions.ScrollMode.Horizontal);
if (scroll != null)
{
//一旦找到注销LayoutUpdated事件
dataGrid.LayoutUpdated -= h;
//隐藏原来DataGrid里的滚动条。
scroll.Opacity = 0;
//设置外置滚动条最大值。
scorllBar1.Maximum = scroll.Maximum;
//设置外置滚动条最小改变值。
scorllBar1.SmallChange= 20;
//滚动条滚动位移量设为原有位移量的0.9倍。
scorllBar1.ViewportSize = scroll.ViewportSize * 0.9;
//执行同步
scorllBar1.ValueChanged += new RoutedPropertyChangedEventHandler<double>(scroll_ValueChanged);
}
}
};
}
/// <summary>
/// 值改变的响应函数。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void scroll_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
this.dataGrid.Scroll(DataGridScrollExtensions.ScrollMode.Horizontal, e.NewValue);
}
PS:因为最后需要把DataGrid的滚动条隐藏起来,所以不能用scorllBar1直接获取DataGrid的滚动条。
Demo下载地址:点击打开链接