【问题标题】: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

    【讨论】:

      【解决方案2】:

      这是关于在 ListBox 上设置滚动条位置的类似问题

      After rebinding Silverlight Listbox control how do you get it listbox to scroll to back to the top?

      由于 DataGrid 也支持 ScrollIntoView 方法,您应该能够使用类似的技术,例如

      theDataGrid.ItemsSource = data; 
      theDataGrid.UpdateLayout(); 
      theDataGrid.ScrollIntoView(theDataGrid.SelectedItem, theDataGrid.Columns[0]);
      

      【讨论】:

        【解决方案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;
            

            【讨论】:

              猜你喜欢
              • 2011-07-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-03-04
              • 1970-01-01
              相关资源
              最近更新 更多