Silverlight之路(十一)

来源:互联网 时间:1970-01-01

关于基金行情,经过第九节中的设置,现在已经可以锁定列头了,而设置了ForzenColumnCount属性后,也可以锁定行头,这在基本的应用中已经够了,但我们这个要求除锁定的行头以后,还有两行需要锁定,就是最下面的“上证”与“平均”,看下图

 

初看上去,好像是合并列的需求,我开始时也是这么想的,于是网上找了好久,最终也没有找到一个合适的方案,倒是找到了一些关于合并列头的方法,可是那个在我们这个需求中没有用。

我又想到了RowStyle与DetailsTemplete实现,但它们的行为也与我们的需求不符,虽然可以做一些控制来模拟,但毕竟都是“猪鼻子插大葱----装像”罢了,于是我们还要继续想想办法。

One day later…

我用了两个表格来实现,

gridQuotes中是正常的各基金数据,dgSummary只有两行“平均”、“上证”;数据分类与绑定很好解决,问题是,如何同步两个表格的各列宽度呢?继续try,最终方案是在gridQuotes表格的LayoutUpdated事件中进行处理,代码如

        void gridQuotes_LayoutUpdated(object sender, EventArgs e)
        {

            for (int i = 1; i < this.dgSummary.Columns.Count; i++)

            {

                this.dgSummary.Columns[i].Width = new DataGridLength(this.gridQuotes.Columns[i + 4].ActualWidth);

            }

        }

 

因为我们的dgSummary表格中前5列是要合并的,就是说dgSummary表格中第一列的列宽要与gridQuotes表格中的前五列保持同步,那么我们在for循环外部设置就可以了(HardCode,不好!)

            this.dgSummary.Columns[0].Width = new DataGridLength(this.gridQuotes.Columns[0].ActualWidth

                + this.gridQuotes.Columns[1].ActualWidth

                + this.gridQuotes.Columns[2].ActualWidth

                + this.gridQuotes.Columns[3].ActualWidth

                + this.gridQuotes.Columns[4].ActualWidth);

 

现在运行起来看看,列宽已经可以同步了,但现在两个表格各自都有自己的水平滚动条(我这个需求中列数比较多,如果列数少,也就不需要水平滚动了),且分别影响两个表格,那我们的下一个问题,就是要解决水平滚动条同步了。

这个问题也不好解决,继续google吧(这里推荐使用google,虽然它经常会访问不了,但毕竟sl的中文资源太少,baidu在这方面就显得太苍白了),中间的各种try我就不说了,直接说结果

我们知道,datagrid控件的属性中,并没有哪个地方可以访问得到滚动条的,但当我们进行模板编辑中却可以在模版中发现有滚动条的存在,那我们就可以在自定义模板时给dgSummary的滚动条加上Scroll事件(后面使用的是ValueChange事件),如果不想自定义模板,也可以使用VisualTreeHelper来辅助帮忙查找,如

        private ScrollBar GetScrollbar(DependencyObject dpObj, string name) 
        {
            for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dpObj); i++)
            {
                var child = VisualTreeHelper.GetChild(dpObj, i);
                ScrollBar scrollBar = child as ScrollBar;
                if (scrollBar != null && scrollBar.Name == name)
                {
                    return scrollBar;
                }
                else
                {
                    scrollBar = GetScrollbar(child, name);
                    if (scrollBar != null)
                    {
                        return scrollBar;
                    }
                }
            }
            return null; 
        }

 

我们也可以用Linq来更“优美”的实现同样的目的

        private ScrollBar GetScrollbar(DependencyObject dpObj, string name) 
        {
            FrameworkElement fe = dpObj as FrameworkElement ;
            return fe.GetVisualDescendants()
          .OfType<ScrollBar>()
          .Where(s => s.Orientation == Orientation.Horizontal)
          .SingleOrDefault();  
        }

 

找到需要的滚动条后,就可以给它注册Scroll事件了

scroll = GetScrollbar(this.dgSummary, "HorizontalScrollbar");

scroll.Scroll += new ScrollEventHandler(scroll_Scroll);

然后我们期望以此来做了滚动条同步

        void scroll_Scroll(object sender, ScrollEventArgs e)
        {
            ScrollBar scroll1 = GetScrollbar(this.gridQuotes, "HorizontalScrollbar");
            if (scroll1 != null)
            {
                scroll1.SetValue(ScrollBar.ValueProperty, e.NewValue);
            }
        }

 

结果呢,滚动条确实同步了,但内容没发生滚动,擦。。。。。。

 

这是肿么了?哪里出问题了呢?这里发现一个小问题,当第一次滚动时,上面的滚动条没有跟着变,于是我们把Scroll改成ValueChange事件,这个小问题就是解决了,但还是只是滚动条在动,内容不动啊。

没招了,我继续Google,于是找到了一个辅助类DataGridScrollExtensions,看它的实现,区别有两处,获取目标滚动条时,它是这样实现的

        private static IScrollProvider GetScrollProvider(DataGrid grid)   
        {
            var p = FrameworkElementAutomationPeer.FromElement(grid) ?? FrameworkElementAutomationPeer.CreatePeerForElement(grid); 
            return p.GetPattern(PatternInterface.Scroll) as IScrollProvider;
        }

 

然后设置目标滚动位置时调用SetScrollPercent方法

            switch (mode)      

            {             

                case ScrollMode.Vertical:     

                    scrollProvider.SetScrollPercent(System.Windows.Automation.ScrollPatternIdentifiers.NoScroll, percent);    

                    break;       

                case ScrollMode.Horizontal:      

                    scrollProvider.SetScrollPercent(percent, System.Windows.Automation.ScrollPatternIdentifiers.NoScroll); 

                    break;        

            } 

 

行不行,我们试下就知道了,改造我们原来的代码

        void scroll_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)

        {

            this.gridQuotes.Scroll(DataGridScrollExtensions.ScrollMode.Horizontal, this.dgSummary.GetScrollPosition(DataGridScrollExtensions.ScrollMode.Horizontal));

            //ScrollBar scroll1 = GetScrollbar(this.gridQuotes, "HorizontalScrollbar");

            //if (scroll1 != null)

            //{

            //    scroll1.SetValue(ScrollBar.ValueProperty, e.NewValue);

            //}

        }

 

真的可以了~!

 

其中的原因,有哪位高人能给解释一下吗,我没太搞清楚。

最后,还有一点小瑕疵,上面的表格的滚动条应该去掉才对,于是我想当然的设置了它不可见,惨,滚动条不好用了!看来设置了它不可见,似乎也同时去掉了它本身,这样不行,那我们就用模板来设置吧,把它的Height设置为0,瞒天过海,ok了,呵呵。

本文来自第八颗流星的博客,原文地址:http://www.cnblogs.com/meteortent/archive/2011/06/22/2085164.html


相关阅读:
Top