数据网格 MVVM 滚动到视图中

7
3个回答

7
看起来这里有两种情况。一种是当您手动选择DataGrid中的项目时,另一种是当SelectedItem的源属性在您的视图模型中更改时。您提供的链接中的行为将触发两者。 ScrollIntoView的工作方式是,如果新选择的项在先前选择的项上方(使其保持在顶部),则向上滚动,如果新选择的项在下方(使其保持在底部),则向下滚动,如果所选项已经对用户可见,则不滚动。因此,您不会总是在DataGrid底部得到所选项。
如果您希望SelectedItem始终显示在网格的顶部(如果可能),则可以在执行grid.ScrollIntoView(grid.SelectedItem, null);之前向下滚动。这会导致一个副作用,即SelectedItem将始终显示在顶部,即使它是通过鼠标、键盘等选择的。
要能够以编程方式滚动DataGrid,您需要创建一个从DataGrid派生的ScrollableDataGrid
public class ScrollableDataGrid : DataGrid
{
    private IScrollProvider m_scrollProvider;
    public ScrollableDataGrid()
    {
        m_scrollProvider = OnCreateAutomationPeer() as IScrollProvider;
    }
    public void ScrollToBottom()
    {
        while (m_scrollProvider.VerticalScrollPercent < 100)
        {
            m_scrollProvider.Scroll(ScrollAmount.NoAmount, ScrollAmount.LargeIncrement);
        }
    }
}

然后,您可以稍微修改行为以获得“滚动到顶部”的效果

void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (sender is ScrollableDataGrid)
    {
        ScrollableDataGrid grid = (sender as ScrollableDataGrid);

        if (grid.SelectedItem != null)
        {
            grid.Dispatcher.BeginInvoke(delegate
            {
                grid.ScrollToBottom();
                grid.UpdateLayout();
                grid.ScrollIntoView(grid.SelectedItem, null);
            });
        }
    }
}

这是一个很好的答案,我认为这是我的唯一选择,但我仍然希望在不创建新控件的情况下实现它...因为我们的数据网格已经是一个自定义控件,用于其他一些更改。 - Theun Arbeider
这个方案很好,只是当垂直滚动条没有显示时会出现问题。在这种情况下,m_scrollProvider.VerticalScrollPercent为-1.0,在ScrollToBottom方法中导致无限循环。将“m_scrollProvider.VerticalScrollPercent >= 0”添加到while循环中可以解决这个问题。总之,这是一个非常有帮助的解决方案--谢谢! - Jersey Dude
又有一个奇怪的情况:我不确定如何生成它,但我遇到了一个情况,其中VerticalScrollPercent达到了99.9999986,永远不会再增加。我将while更改为:while (Math.Round(m_scrollProvider.VerticalScrollPercent, 0) < 100 && m_scrollProvider.VerticalScrollPercent >= 0 && --maxIterations > 0)。我添加了maxIterations检查以防止任何其他情况挂起应用程序。 - Jersey Dude

0
void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (sender is DataGrid)
        {
            DataGrid grid = (sender as DataGrid);
            if (grid.SelectedItems.Count > 1) // <-------- Add row
                return; //<-------- Add row
            if (grid.SelectedItem != null)
            {
                grid.Dispatcher.BeginInvoke(new Action (delegate()
                {                        
                    grid.UpdateLayout();
                    grid.ScrollIntoView(grid.SelectedItem, null);

                }));
            }
        }
    }

0

对于一个数据网格,你知道记录编号:

在你的模块声明中....

Dim dv As DataView

Dim cm As CurrencyManager

在你的代码中定义数据网格的地方...
DataGrid1.DataSource = ds.Tables("JoinedTables").DefaultView

dv = New DataView(ds.Tables("JoinedTables"))

cm = CType(Me.BindingContext(dv), CurrencyManager)

当你想将你的记录编号设置为最顶部时

Public Sub SetPosition(ByVal recordnumber As Integer)

     On Error Resume Next

     'set position to bottom of grid 
     DataGrid1.CurrentRowIndex = ds.Tables(0).Rows.Count
     DataGrid1.Update()

     'set position at record number
     DataGrid1.CurrentRowIndex = recordnumber
     cm.Position = recordnumber

End sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接