开发者

Silverlight DataGrid scrollbar synchronization

I have 2 Silverlight DataGrids one on top of another. 开发者_如何学运维I want to synchronize their horizontal scrollbars. I have tried to put them both in separate scrollviewers and set the horizontal offset of source scrollviewer to horizontal offset of target scrollviewer but that does not work, the below DataGrid scrollviewer disappers.I think that might be because these Datagrid are inside a StackPanel? I also tried to put these 2 grids in a third grid and apply scrollviewer on that but that does not work either

Does anyone have an idea how to go about this? Thanks a lot in advance


I did this in SL4, have no idea if it works in SL3, sorry. The docs state that the API is there but I have not tried it.

The trick is to use automation peers. Get the scroll pattern automation peers for both grids. When scrolling happens on one grid, scroll the other one through the automation peer.

To make this more concrete, assuming we have 2 grids, named _dgGrowth and _dgTotals:

using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

    public partial class MyPageWithGrids : Page {
...
        private ScrollBar _sbGrowth, _sbTotals;
        private AutomationPeer _peerGrowth, _peerTotals;
        private bool _ignoreScrollEvents;

        private void OnPageLoaded(object sender, RoutedEventArgs e) {

            _sbGrowth = GetHorizontalScrollBar(_dgGrowth);
            if (_sbGrowth != null) {
                _sbGrowth.Scroll += OnScrollGrowthGrid;
            }
            _sbTotals = GetHorizontalScrollBar(_dgTotals);
            if (_sbTotals != null) {
                _sbTotals.Scroll += OnScrollTotalsGrid;
            }

            _peerGrowth = FrameworkElementAutomationPeer.CreatePeerForElement(_dgGrowth);
            _peerTotals = FrameworkElementAutomationPeer.CreatePeerForElement(_dgTotals);
        }

        private ScrollBar GetHorizontalScrollBar(DataGrid parentGrid) {
            return parentGrid.Descendents().OfType<ScrollBar>().FirstOrDefault(sb => sb.Name == "HorizontalScrollbar");
        }

        private void OnScrollTotalsGrid(object sender, ScrollEventArgs e) {

            if (! _ignoreScrollEvents) {
                SyncHorizontalScroll(_peerTotals, _peerGrowth);
            }
        }

        private void OnScrollGrowthGrid(object sender, ScrollEventArgs e) {

            if (! _ignoreScrollEvents) {
                SyncHorizontalScroll(_peerGrowth, _peerTotals);
            }
        }

        private void SyncHorizontalScroll(AutomationPeer source, AutomationPeer copy) {

            IScrollProvider sourceProvider = null;
            if (source != null) {
                sourceProvider = (IScrollProvider) source.GetPattern(PatternInterface.Scroll);
            }
            IScrollProvider copyProvider = null;
            if (copy != null) {
                copyProvider = (IScrollProvider) copy.GetPattern(PatternInterface.Scroll);
            }

            if (sourceProvider != null && copyProvider != null) {

                _ignoreScrollEvents = true;

                // scroll copy at horizontal position of source, and keep vertical position
                copyProvider.SetScrollPercent(sourceProvider.HorizontalScrollPercent, copyProvider.VerticalScrollPercent);

                _ignoreScrollEvents = false;
            }
        }
    }

What is not shown is setting up the Loaded event to OnPageLoaded and the Descendants() method found in this question.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜