OK, tôi đã dành một vài ngày trong cỏ dại với cái này, và tôi nghĩ rằng tôi đã có một xử lý trên đó.
Đầu tiên, một phần ma thuật quan trọng. Để phân trang hoạt động chính xác, máy nhắn tin phải biết tổng số mục, bất kể có bao nhiêu mục được truy vấn trả về. Nếu truy vấn trả về mọi thứ, số lượng mục rõ ràng là số lượng các mục được trả về. Đối với phân trang thông minh, số mục vẫn là tổng số mục có sẵn, mặc dù truy vấn chỉ trả về những gì được hiển thị. Với tính năng lọc, ngay cả tổng số mục có sẵn sẽ thay đổi mỗi khi bộ lọc thay đổi.
Bộ điều khiển Datapager Silverlight có thuộc tính được gọi là ItemCount. Nó là chỉ đọc và không thể được databound trong XAML, hoặc thiết lập trực tiếp trong mã. Tuy nhiên, nếu điều khiển người dùng có chứa máy nhắn tin có một DataContext thực hiện IPagedCollectionView, thì đối tượng bối cảnh dữ liệu phải thực hiện một thuộc tính ItemCount với thông báo PropertyChanged, và DataPager có vẻ như đã chọn điều này một cách tự động.
Thứ hai, tôi đặc biệt khuyên bạn nên sử dụng hình ảnh tuyệt đẹp series of blog posts on RIA Services của Brad Abrams, đặc biệt là hình ảnh này trên ViewModel. Nó chứa hầu hết những gì bạn cần để làm cho phân trang và lọc công việc, mặc dù nó thiếu phần quan trọng về quản lý số mục. Mẫu tải xuống của ông cũng chứa một khung cơ bản rất tốt để triển khai ModelViewViewModel (MVVM). Cảm ơn, Brad!
Vì vậy, dưới đây là cách làm cho số mục hoạt động. (Mã này đề cập đến một ORM tùy chỉnh, trong khi mã của Brad sử dụng Khung thực thể, giữa hai bạn có thể tìm ra những gì bạn cần trong môi trường của mình.)
Đầu tiên, ORM của bạn cần hỗ trợ tính số lượng bản ghi, có và không có bộ lọc. Đây là mã dịch vụ tên miền của tôi, giúp số lượng sẵn có cho RIA Services:
[Invoke]
public int GetExamCount()
{
return Context.Exams.Count();
}
[Invoke]
public int GetFilteredExamCount(string descriptionFilter)
{
return Context.Exams.GetFilteredCount(descriptionFilter);
}
Lưu ý thuộc tính [Invoke]. Bạn cần điều này cho bất kỳ phương thức DomainService nào không trả về một bộ sưu tập Entity hoặc Entity.
Bây giờ cho mã ViewModel. Bạn cần một ItemCount, tất nhiên. (Đây là ví dụ của Brad.)
int itemCount;
public int ItemCount
{
get { return itemCount; }
set
{
if (itemCount != value)
{
itemCount = value;
RaisePropertyChanged(ItemCountChangedEventArgs);
}
}
}
Phương thức LoadData sẽ chạy truy vấn để nhận tập hợp hàng hiện tại để hiển thị trong DataGrid. (Điều này không thực hiện sắp xếp tùy chỉnh, nhưng đó là một bổ sung dễ dàng.)
EntityQuery<ExamEntity> query =
DomainContext.GetPagedExamsQuery(PageSize * PageIndex, PageSize, DescriptionFilterText);
DomainContext.Load(query, OnExamsLoaded, null);
Phương thức gọi lại sau đó chạy truy vấn để nhận số lượng. Nếu không có bộ lọc nào đang được sử dụng, chúng tôi sẽ tính số lượng cho tất cả các hàng; nếu có bộ lọc, thì chúng tôi sẽ tính số lượng hàng được lọc.
private void OnExamsLoaded(LoadOperation<ExamEntity> loadOperation)
{
if (loadOperation.Error != null)
{
//raise an event...
ErrorRaising(this, new ErrorEventArgs(loadOperation.Error));
}
else
{
Exams.MoveCurrentToFirst();
if (string.IsNullOrEmpty(DescriptionFilterText))
{
DomainContext.GetExamCount(OnCountCompleted, null);
}
else
{
DomainContext.GetFilteredExamCount(DescriptionFilterText, OnCountCompleted, null);
}
IsLoading = false;
}
}
Ngoài ra còn có một phương pháp gọi lại cho số lượng:
void OnCountCompleted(InvokeOperation<int> op)
{
ItemCount = op.Value;
TotalItemCount = op.Value;
}
Với bộ ItemCount, kiểm soát DataPager nhặt nó lên, và chúng tôi có phân trang với bộ lọc và truy vấn thông minh sẽ chỉ trả lại các hồ sơ để được hiển thị!
LINQ giúp truy vấn dễ dàng với .Skip() và .Take(). Làm điều này với ADO.NET thô khó hơn. Tôi đã học cách thực hiện điều này bằng cách lấy ra một truy vấn do LINQ tạo ra.
SELECT * FROM
(select ROW_NUMBER() OVER (ORDER BY Description) as rownum, *
FROM Exams as T0 WHERE T0.Description LIKE @description) as T1
WHERE T1.rownum between @first AND @last ORDER BY rownum
Điều khoản "chọn ROW_NUMBER() OVER (ORDER BY Description) dưới dạng rownum" là phần thú vị, vì không có nhiều người sử dụng "OVER". Mệnh đề này sắp xếp bảng trên Mô tả trước khi gán số hàng và bộ lọc cũng được áp dụng trước khi số hàng được gán. Điều này cho phép SELECT bên ngoài lọc số hàng, sau khi sắp xếp và lọc.
Vậy có, phân trang thông minh với tính năng lọc, trong Dịch vụ RIA và Silverlight!
Khi tôi gặp các vấn đề như thế này với các khung công tác có nhiệm vụ thực hiện các tác vụ phổ biến, trong trường hợp này phân trang, dễ dàng hơn là một chút lo lắng. Để sử dụng RIA hoặc không sử dụng RIA đó là câu hỏi ... – sipwiz
Vâng, đó là một câu hỏi mở cho bây giờ. Dịch vụ RIA cho Silverlight 3 và VS 2008 là khá nhiều người chết; những gì có sẵn bây giờ là phiên bản beta công khai, sẽ không được nâng cao và sẽ chỉ được hỗ trợ đến tháng 12. Vì vậy, các dịch vụ RIA cho Silverlight 4 và VS 2010 là tùy chọn. Nó đang ở trạng thái RC2 bây giờ; Tôi sẽ kiểm tra nó ngay sau khi nó chạm trạng thái phát hành. FWIW, Brad Abrams nói để cho DataGrid Silverlight thực hiện phân trang, nhưng vẫn có vấn đề về lọc tùy chỉnh, và đó là những gì thực sự đã giết RIA Services cho tôi lúc đầu. Chúng ta phải có khả năng lọc trên máy chủ. –