在更新silverlight数据网格的ItemSource时保持滚动位置

时间:2009-12-03 11:47:32

标签: silverlight silverlight-3.0 datagrid scroll

我在Silverlight应用程序中使用DataGrid来显示一些在计时器上刷新的数据。我的问题是,当发生这种情况时,网格中的垂直滚动条重置到顶部,而我希望它保持在相同的位置。有谁知道我怎么能做到这一点?

我已尝试覆盖网格上的ItemsSource属性以存储垂直滚动位置然后重置它,但这只会影响滚动条并且不会强制显示正确的行。有没有办法强迫这种行为?

5 个答案:

答案 0 :(得分: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]);

答案 1 :(得分:1)

上次看的时候,我找不到合适的答案。我想保持在网格中选择当前元素,但这不适用于ICollectionView刷新(我使用MVVM并从服务器获取自动更新)。

ScrollIntoView()对我来说不是一个选项,因为当前所选的项目可能不在视图中。让CurrentChanged事件失控也很麻烦。

最后,我使用了Infragistics网格,它开箱即用。问题解决了我。

您可以查看DevExpress免费网格。我认为它具有相同的好行为(我测试了它,但我不记得结果)。

答案 2 :(得分:0)

您可以尝试在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 :(得分:0)

我也遇到过这个问题。我通过记住要滚动到的项目,然后重新绑定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 :(得分:0)

我修改了CodeMaster的解决方案,因此您不需要类级变量。将此代码放在更新ItemsSource的方法中。它将动态创建事件处理程序,附加它,然后将其分离。

EventHandler MyDataGrid_LayoutUpdated = null;

MyDataGrid_LayoutUpdated = (s, e) =>
    {
        MyDataGrid.ScrollIntoView(dataItem, MyDataGrid.Columns[0]);
        MyDataGrid.LayoutUpdated -= MyDataGrid_LayoutUpdated;
    };

MyDataGrid.LayoutUpdated += MyDataGrid_LayoutUpdated;