2010-02-18 23 views
13

Tôi vẫn đang cố gắng đặt chân lên Silverlight và RIA Services, và tất nhiên bắt đầu với một số nội dung thú vị hơn như lưới và phân trang thông minh. Tôi có thể kết nối với RIA Services (sử dụng ORM được phát triển tại nhà, không phải L2S hoặc EF), lấy dữ liệu trên lưới và kết nối với một DataPager. Dịch vụ miền hoạt động tốt với ORM được phát triển tại nhà, ít nhất là đối với các truy vấn. (Vẫn làm việc trên CRUD đầy đủ.) Tuy nhiên, vẫn còn một vấn đề:Silverlight, DataPager, RIA Services và phân trang thông minh

  1. Để hỗ trợ các ứng dụng người dùng, tôi cần phân loại người dùng kiểm soát và lọc, ngoài việc phân trang thông minh (chỉ chạy các truy vấn cho các hàng cần thiết để hiển thị) và nhóm.

  2. Cho đến nay, tôi không thấy gì trong DataGrid hoặc DataPager để bên ngoài các khả năng này để các tham số lọc, sắp xếp và phân trang có thể được chuyển tới máy chủ để xây dựng truy vấn thích hợp.

  3. Các tập dữ liệu có khả năng khá lớn; bảng của tôi mà tôi đã chọn để tạo mẫu có thể có tới 35.000 mục nhập tại một số khách hàng và tôi chắc rằng có nhiều bảng khác lớn hơn nhiều mà tôi sẽ phải giải quyết tại một số điểm. Vì vậy, khía cạnh "phân trang thông minh" là điều cần thiết.

Ý tưởng, đề xuất, hướng dẫn và gạch nerf đều được chào đón.

Trả lời

11

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!

+3

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

+0

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ủ. –

4

Dưới đây là giải pháp nhanh chóng và dơ bẩn (mà tôi đã đi cho):

Chỉ cần di chuyển DomainDataSource của bạn để ViewModel của bạn! Làm xong!

Có thể không chính xác tuyệt đối cho khả năng kiểm thử và có thể một số hạn chế khác mà tôi chưa phát hiện, nhưng cá nhân tôi không quan tâm đến điều đó cho đếnsomething better comes along.

Bên trong ViewModel của bạn chỉ cần nhanh chóng các nguồn dữ liệu:

// Feedback DataSource 
_dsFeedback = new DomainDataSource(); 
_dsFeedback.DomainContext = _razorSiteDomainContext; 
_dsFeedback.QueryName = "GetOrderedFeedbacks"; 
_dsFeedback.PageSize = 10; 
_dsFeedback.Load(); 

và cung cấp một tài sản bindable:

private DomainDataSource _dsFeedback { get; set; } 
public DomainDataSource Feedback 
{ 
    get 
    { 
     return _dsFeedback; 
    } 
} 

Và thêm DataPager của bạn để XAML của bạn:

<data:DataPager Grid.Row="1" 
        HorizontalAlignment="Stretch" 
        Source="{Binding Feedback.Data}" 
        Margin="0,0,0,5" /> 

    <data:DataGrid ItemsSource="{Binding Feedback.Data}"> 


PS. Nhờ có 'Francois' từ trang được liên kết ở trên. Tôi thậm chí không nhận ra rằng tôi có thể lấy DomainDataSource ra khỏi XAML cho đến khi tôi nhìn thấy bình luận của bạn!

Các vấn đề liên quan