2011-09-08 34 views
28

Tôi có một ứng dụng WPF bằng cách sử dụng mô hình MVVM mà đôi khi phải hiển thị một waitcursor khi nó đang bận làm một cái gì đó người dùng phải chờ đợi. Nhờ sự kết hợp của các câu trả lời trên trang này: display Hourglass when application is busy, tôi có một giải pháp hầu như hoạt động (mặc dù nó không thực sự là MVVM trong tinh thần). Bất cứ khi nào tôi làm điều gì đó tốn nhiều thời gian trong viewmodels của tôi, tôi làm điều này:Làm thế nào để hiển thị một waitcursor khi các ứng dụng WPF là bận databinding

using (UiServices.ShowWaitCursor()) 
{ 
.. do time-consuming logic 
this.SomeData = somedata; 
} 

(ShowWaitCursor() trả về một IDisposable cho thấy waitcursor cho đến khi nó đang được xử lý) Dòng cuối cùng trong ví dụ của tôi là nơi tôi thiết lập một số tài sản. Thuộc tính này bị ràng buộc trong XAML của tôi, ví dụ: như thế này:

<ItemsControl ItemsSource="{Binding SomeData}" /> 

Tuy nhiên, vì đây có thể là một danh sách dài các đối tượng và đôi khi với bảng dữ liệu phức tạp, vv. Kể từ khi ràng buộc này diễn ra bên ngoài của tôi bằng cách sử dụng báo cáo waitcursor sẽ biến mất trước khi chờ đợi thực sự là hơn cho người dùng.

Vì vậy, câu hỏi của tôi là làm thế nào để làm một waitcursor trong một ứng dụng MVVM WPF mà mất databinding vào tài khoản?

Trả lời

82

Câu trả lời của Isak không phù hợp với tôi, vì nó không giải quyết được vấn đề về cách hành động khi thời gian chờ thực sự kết thúc cho người dùng. Tôi đã làm điều này: Mỗi khi tôi bắt đầu làm một cái gì đó timeconsuming, tôi gọi một phương pháp trợ giúp. Phương thức trợ giúp này thay đổi con trỏ và sau đó tạo một DispatcherTimer sẽ được gọi khi ứng dụng không hoạt động. Khi nó được gọi là nó đặt mousecursor lại:

/// <summary> 
/// Contains helper methods for UI, so far just one for showing a waitcursor 
/// </summary> 
public static class UiServices 
{ 

    /// <summary> 
    /// A value indicating whether the UI is currently busy 
    /// </summary> 
    private static bool IsBusy; 

    /// <summary> 
    /// Sets the busystate as busy. 
    /// </summary> 
    public static void SetBusyState() 
    { 
      SetBusyState(true); 
    } 

    /// <summary> 
    /// Sets the busystate to busy or not busy. 
    /// </summary> 
    /// <param name="busy">if set to <c>true</c> the application is now busy.</param> 
    private static void SetBusyState(bool busy) 
    { 
      if (busy != IsBusy) 
      { 
       IsBusy = busy; 
       Mouse.OverrideCursor = busy ? Cursors.Wait : null; 

       if (IsBusy) 
       { 
        new DispatcherTimer(TimeSpan.FromSeconds(0), DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick, Application.Current.Dispatcher); 
       } 
      } 
    } 

    /// <summary> 
    /// Handles the Tick event of the dispatcherTimer control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> 
    private static void dispatcherTimer_Tick(object sender, EventArgs e) 
    { 
      var dispatcherTimer = sender as DispatcherTimer; 
      if (dispatcherTimer != null) 
      { 
       SetBusyState(false); 
       dispatcherTimer.Stop(); 
      } 
    } 
} 
+0

lớn thực hiện! Điều này làm việc hoàn hảo cho tôi khi thời gian tiêu thụ đang xảy ra trong hoạt động ràng buộc giao diện người dùng của bên thứ ba; khi tôi không thực sự biết khi nào nó được thực hiện. Cảm ơn bạn! –

+0

Tôi sẽ thay đổi điều này để sử dụng một số thay vì một bool. Bằng cách đó, nhiều địa điểm có thể nói rằng họ cần con trỏ đợi và nó sẽ vẫn còn cho đến khi tất cả chúng đều từ bỏ nó. –

+1

Rất tuyệt! Cảm ơn bạn! – Dummy01

6

Điều tôi đã làm trong quá khứ là xác định các thuộc tính boolean trong chế độ xem biểu thị cho biết rằng đang tính toán dài. Ví dụ: IsBusy được đặt thành true khi làm việc và sai khi không hoạt động.

Sau đó, trong chế độ xem, tôi liên kết với điều này và hiển thị thanh tiến trình hoặc spinner hoặc tương tự trong khi thuộc tính này là đúng. Cá nhân tôi chưa bao giờ đặt con trỏ bằng cách sử dụng phương pháp này nhưng tôi không thấy tại sao nó không thể thực hiện được.

Nếu bạn muốn kiểm soát nhiều hơn và boolean đơn giản là không đủ, bạn có thể sử dụng VisualStateManager mà bạn lái xe từ chế độ xem của bạn. Với cách tiếp cận này, bạn có thể chỉ định chi tiết giao diện người dùng sẽ trông như thế nào tùy thuộc vào trạng thái của chế độ xem.

1

Ngoài đóng góp Isak Savo, bạn có thể muốn có một cái nhìn tại Brian Keating's blog cho một mẫu làm việc.

7

Vì vậy, tôi không thích sử dụng OverrideCursor vì tôi đã có nhiều cửa sổ và tôi muốn những người hiện không thực hiện một cái gì đó để có con trỏ mũi tên bình thường.

Đây là giải pháp của tôi:

<Window.Style> 
    <Style TargetType="Window"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding IsBusy}" Value="True"> 
       <Setter Property="Cursor" Value="Wait" /> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</Window.Style> 
<Grid> 
    <Grid.Style> 
     <Style TargetType="Grid"> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding IsBusy}" Value="True"> 
        <Setter Property="IsHitTestVisible" Value="False" /> <!-- Ensures wait cursor is active everywhere in the window --> 
        <Setter Property="IsEnabled" Value="False" /> <!-- Makes everything appear disabled --> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </Grid.Style> 
    <!-- Window controls go here --> 
</Grid> 
Các vấn đề liên quan