惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
The Last Watchdog
The Last Watchdog
Cyberwarzone
Cyberwarzone
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Cloudflare Blog
V
V2EX
博客园_首页
博客园 - 聂微东
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
T
Tenable Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
SecWiki News
SecWiki News
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
D
DataBreaches.Net
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
D
Docker
P
Proofpoint News Feed

博客园 - *小小黄*

List<T>的Sort,Find,Exists等的使用(摘抄) JQuery常用代码1 使用Telerik控件时出现Failed to create designer 的解决方法 GridView 笔记 - *小小黄* - 博客园 Telerik Rad 笔记 一 Silverlight学习笔记四:如何通过自定义ComboBox实现SelectedValue Silverlight学习笔记三:如何自定义DataGrid的Header Silverlight学习笔记二(续) Silverlight学习笔记一:DataGrid如何处理鼠标的滚轮事件 SQL2005快照 在ASP.NET中使用HTTP压缩 Web注册表单设计样式的研究(下) Web注册表单设计样式的研究(上) 禁用aspx页面的客户端缓存 DataGrid中没有数据时显示表头(转) 在 Windows Vista 上安裝 Reporting Services IIS7中访问Access数据库报错的解决方案 解决“无法删除文件:无法读源文件或磁盘” AjaxControlToolkit中的CalendarExtender被遮挡的解决方法
Silverlight学习笔记二:DataGrid 服务器端分页、排序的实现
*小小黄* · 2008-12-25 · via 博客园 - *小小黄*

先看一下效果。美工不好,见笑。呵呵。
Silverlight DataGrid 本身是不带分页功能的,同时他的排序也是针对当前页面的内容进行排序的,而这两样功能在实际的项目中都是必须带的。上网搜索了一下,好像目前还没有那篇文章介绍过如何实现这两个常用的功能,看样子只要自己动手了。呵呵。


下面我们来一步一步实现这些功能。(以下都以NorthWind数据库为演示) 第一步,我们先实现分页。

要分页,首先要在WCF上加上一个分页获取数据的方法。先上代码。  1   [OperationContract]
 2   public List<Products> GetProductsPaging(int start, int limit, string sort, string dir, out int TotalPage)
 3   {
 4   NorthWindLinqDataContext db = new NorthWindLinqDataContext();
 5   string sql;
 6   sql = "select count(*) as c from Products";
 7   int TotalCount = db.ExecuteQuery<int>(sql).Single();  
 8   TotalPage = Convert.ToInt32(Math.Ceiling((double)TotalCount / (double)limit));
 9   sql = "with a as (SELECT *, row_number() over (order by {0}) as rownumber FROM Products) select * from a where rownumber between {1} and {2}";
10   sql = string.Format(sql, sort + " " + dir, start , start+limit-1);  
11   var query = db.ExecuteQuery<Products>(sql);
12   return query.ToList();
13   }
14 

代码比较简单,用了sql2005的分页方法,就不做解释了,至于这分页方法的效率怎么样不是本次学习的重点,先不管了。

数据库访问使用LinqToSQL做的,本来想用Linq实现分页功能的,但是忙活了半天,最终以失败告终,主要的问题是,我没办法在Linq中实现动态排序,网上也没有找到一个合适的方法,只能写n个ifelse进行排序,就像下面的代码:

1    var products = from p in db.Products
2                         select p;
3    if (dir == "ProductName")
4    products = products.OrderBy(p => p.ProductName);
5    else if (dir == "ProductID")
6    products = products.OrderBy(p => p.ProductID);
7    .......

这样写的话,虽然功能能实现,但是实在是有点弱智。要写上一大堆的代码,真的不如写sql呢。最终,还是没有搞定这个问题,只好写sql语句了。如果大家有什么好的办法能实现的话,请留言告诉我。谢谢了!

ok,到此分页的基本功能搞定了,DataGrid已经可以获取分页的数据了。但是,这个DataGrid和Web上的不一样,没有Pager,晕,只要手工写一个Pager控件了。

第二步,实现Pager。

    动手之前,老办法。先上网找现成的,呵呵,不错,这次终于有点结果了,网上不少这样的例子,在silverlight.net上找了一个Pager,先用着再说。呵呵。
这个是地址http://www.13sides.com/page/A-Generic-Pager-Control.aspx,大家自己去看吧,用法很简单。
    现在把代码整合起来,ok,已经可以正确的分页了。哈哈。接下来,我们来实现排序。 

第三步,实现排序。

    要排序,当然是要点击ColumnHeader了,在DataGrid中找ColumnHeader的点击事件,晕,没有。不会吧,这个微软,怎么搞的啊,虽然Silverlight都2.0了,但是怎么看都还是像个半成品啊,这样常用的事件都没有。半成品就半成品吧,继续手工实现吧。
    又是老办法,上网找现成的,呵呵,两种方案,一种是把Header改成模板,然后里面放上Button,这样就可以实现了。还有一种,有人提到了用DataGrid的HitTest方法。呵呵,第一个有点费事,每个Header都要改,第二个看起来酷一点,所以我选择了第二种。
试验了一下,晕,HitTest怎么成了不可访问,受保护级别限制。再查MSDN,呵呵,原来2.0里面该成了VisualTreeHelper.FindElementsInHostCoordinates了。ok,下面上代码:
在DataGrid的MouseLeftButtonDown写。这里有个奇怪的问题,点击ColumnHeader并不会触发MouseLeftButtonUp事件。真的搞不明白。

 1   private void dgData_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 2   {
 3   //获取点击的ColumnHeader
 4   var u = from element in VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(null), dgData)
 5   where element is DataGridColumnHeader
 6   select element;
 7 
 8   if (u.Count() == 1)
 9   {
10   DataGridColumnHeader header = (DataGridColumnHeader)u.Single();
11   //为什么要把这个header保存下来,下面会介绍原因的。
12   sortHeader = header;
13   //获取到字段的名称。
14   string headername = header.Content.ToString();
15   //跟现在的排序字段比较一下,确定应该是 desc 还是 asc
16   string newsort = header.Content.ToString();
17   if (newsort == sort)
18   dir = dir == "desc" ? "asc" : "desc";
19   else
20   dir = "asc";
21   sort = newsort;
22   //绑定数据
23   BindGrid();
24   e.Handled = true;
25   }
26   else
27   e.Handled = false;
28   }

    好,到此,整个分页、排序的功能就基本上完成了。
    呵呵,仔细用一下程序发现,我们在实现了排序之后,DataGrid 然而会自作聪明的帮我们的数据又排了一下,并且,DataGrid默认是支持列拖动的,当我们拖动列时,会触发排序,导致结果和用户预计的不一样。那怎么解决呢,
    直接在DataGrid中设置 CanUserSortColumns="False"和CanUserReorderColumns="False"。就可以解决了。   

    再在测试一下,发现在排序之后,ColumnHeader上面并没有显示标示排序方向的小箭头,查了一下,MSDN上面在介绍 DataGrid 样式和模板的时候,提到过DataGridColumnHeader 状态里面有SortAscending和SortDescending这两种状态,ok,我们就接着写了个方法,来设置Header的状态。在上面MouseLeftButtonDown中我们曾经把排序的Header保存了下来,就是为了在这里使用的。代码如下:

1    private void setColumnSortState()
2    {
3      if (dir == "asc")
4          VisualStateManager.GoToState(sortHeader, "SortAscending"false);
5      else
6          VisualStateManager.GoToState(sortHeader, "SortDescending"false);
7    } 

    很简单,但是有个奇怪的问题,就是在排序之后,设置了Header的状态并不能保存下来,鼠标移动,那个小箭头就会消失,具体原因我也不明白,我不太清楚VisualStateManager.GoToState在设置了Header状态是不是和DataGrid自带的排序功能有关联,才导致了排序的小箭头会自动消失,或者在这里根本就不应该用这个方法。暂时我没有去考虑这个问题,为了让排序小箭头能正确显示,我只好在Grid的MouseMove和LayoutUpdated事件里都调用了setColumnSortState(),用来保证小箭头可以正确显示。
    至此,整个分页、排序的功能全部完成。除了那个小箭头显示的处理不完美之外,其它到也没有什么大问题。我会在后面的学习中,来解决这个问题。

    另外,祝大家圣诞快乐!!!

补充:

重新修改了关于排序状态的实现。请见:  

Silverlight学习笔记二(续)