【问题标题】:Datagrid MVVM Scroll into viewDatagrid MVVM 滚动到视图中
【发布时间】:2011-06-15 16:55:03
【问题描述】:

您好,

我已经设法使用http://www.codeproject.com/Tips/125583/ScrollIntoView-for-a-DataGrid-when-using-MVVM.aspx 滚动到所选项目,但这只会滚动到所选项目。

我希望所选项目显示在数据网格的顶部,目前它显示在数据网格的底部。

有没有办法做到这一点?

【问题讨论】:

    标签: c# silverlight mvvm datagrid


    【解决方案1】:

    这里似乎有两种情况。一种是手动选择DataGrid 中的项目,另一种是SelectedItem 的源属性在视图模型中发生更改。您提供的链接中的行为将同时触发。

    ScrollIntoView 的工作方式是,如果新选择的项目在先前选择的项目之上(保留在顶部),它将向上滚动,如果新选择的项目在下方(保留在底部),则向下滚动,并且如果所选项目已经对用户可见,则根本不滚动。所以你不会总是在DataGrid的底部得到选中的项目

    如果您希望SelectedItem 始终显示在网格顶部(如果可能),您可以在执行grid.ScrollIntoView(grid.SelectedItem, null); 之前滚动到底部来实现。这样做的副作用是SelectedItem始终显示在顶部,即使它被鼠标、键盘等选中。

    为了能够以编程方式滚动 DataGrid,您需要创建一个派生自 DataGridScrollableDataGrid

    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);
                });
            }
        }
    }
    

    【讨论】:

    • 这是一个很好的答案,我认为这是我唯一的选择,但我仍然希望无需创建新控件就可以实现。因为我们的数据网格已经是用于其他一些更改的自定义控件。跨度>
    • 这很好,除非垂直滚动条没有显示。在这种情况下,m_scrollProvider.VerticalScrollPercent 为 -1.0,导致 ScrollToBottom 方法出现无限循环。在 while 循环中添加“m_scrollProvider.VerticalScrollPercent >= 0”可以解决此问题。无论如何,这是一个非常有用的解决方案——谢谢!
    • 一个更奇怪的情况:我不知道如何生成它,但我遇到了 VerticalScrollPercent 达到 99.9999986 并且永远不会更高的情况。我将 while 更改为:while (Math.Round(m_scrollProvider.VerticalScrollPercent, 0) = 0 && --maxIterations > 0)。我添加了 maxIterations 检查以防止任何其他情况下挂起应用程序。
    【解决方案2】:
    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);
    
                    }));
                }
            }
        }
    

    【讨论】:

      【解决方案3】:

      对于数据网格,您知道记录号:

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

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-29
        • 2013-06-23
        • 2013-02-10
        • 2010-12-27
        • 2014-02-24
        • 1970-01-01
        • 2017-11-24
        • 1970-01-01
        相关资源
        最近更新 更多