【问题标题】:Maintain scroll position on updating the ItemSource of a silverlight datagrid在更新 Silverlight 数据网格的 ItemSource 时保持滚动位置
【发布时间】:2010-12-22 19:19:37
【问题描述】:
我在silverlight 应用程序中使用DataGrid 来显示一些在计时器上刷新的数据。我的问题是,当发生这种情况时,网格中的垂直滚动条会重置到顶部,而我希望它保持在同一位置。有谁知道我怎么能做到这一点?
我尝试覆盖网格上的 ItemsSource 属性以存储垂直滚动位置,然后将其重置,但这只会影响滚动条并且不会强制显示正确的行。有没有办法强制这种行为?
【问题讨论】:
标签:
silverlight
silverlight-3.0
datagrid
scroll
【解决方案1】:
您可以尝试通过 UI 线程设置 SelectedItem,以便 UI 可以自行刷新,
像这样
private void Button_Click(object sender, RoutedEventArgs e)
{
Person p = new Person() { Name="sss",Age=11}; //datagird's itemsSource is Collection<person>
people.Add(p);
dg.SelectedItem = p; //dg is my datagrid name
Dispatcher.BeginInvoke(() => { dg.SelectedItem = p; });
}
我假设新行是通过 ViewModel 加载的,所以这就是为什么将 BeginInvoke 放在那里是有意义的。由于 ViewModel 操作在不同的线程上运行,并且仅单独设置 SelectedItem 可能无法正常工作,因此这适用于 someone else
【解决方案3】:
我也遇到过这个问题。我通过记住要滚动到的项目来解决它,然后重新绑定 DataGrid。我处理 LayoutUpdated 事件以实现所需的功能:
void MyDataGrid_LayoutUpdated(object sender, EventArgs e)
{
// Reference the data item in the list you want to scroll to.
object dataItem = yourDataItem;
// Make sure the item is not null and didn't already scroll to the item.
if (dataItem != null && this.dataItemScrolledTo != dataItem)
{
// Remember the item scrolled to.
this.dataItemScrolledTo = dataItem;
// Scroll datagrid to the desired item.
MyDataGrid.ScrollIntoView(dataItem, MyDataGrid.Columns[0]);
}
}
【解决方案4】:
我上次查看时找不到合适的答案。我想在网格中保持当前元素处于选中状态,但这不适用于 ICollectionView 刷新(我使用 MVVM 并从服务器获取自动更新)。
ScrollIntoView() 对我来说不是一个选项,因为当前选择的项目可能不在视图中。让CurrentChanged 事件失控也很麻烦。
最后,我使用了 Infragistics 网格,它开箱即用。为我解决了问题。
您可以查看 DevExpress 免费网格。我认为它有同样好的行为(我测试了它,但我不记得结果了)。
【解决方案5】:
我已经修改了 CodeMaster 的解决方案,这样您就不需要类级别的变量了。将此代码放在更新 ItemsSource 的方法中。它将动态创建事件处理程序,附加它,然后分离它。
EventHandler MyDataGrid_LayoutUpdated = null;
MyDataGrid_LayoutUpdated = (s, e) =>
{
MyDataGrid.ScrollIntoView(dataItem, MyDataGrid.Columns[0]);
MyDataGrid.LayoutUpdated -= MyDataGrid_LayoutUpdated;
};
MyDataGrid.LayoutUpdated += MyDataGrid_LayoutUpdated;