MVVM Wait Cursor如何在调用命令期间设置.wait游标?

use*_*350 22 wpf cursor mvvm wait

场景:用户单击View上的按钮这会调用ViewModel上的命令,DoProcessing如何以及Wait光标设置在哪里,考虑到View和ViewModel的责任?

为了清楚起见,我只是想在命令运行时将DEFAULT游标更改为沙漏.命令完成后,光标mut变回箭头.(这是我正在寻找的同步操作,我希望UI能够阻止).

我在ViewModel上创建了一个IsBusy属性.如何确保应用程序的鼠标指针发生变化?

Sha*_*ngh 29

我在我的应用程序中成功使用它:

/// <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, System.Windows.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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是从这里开始的.Courtsey huttelihut.

SetBusyState每次您认为要执行任何耗时的操作时,都需要调用该方法.例如

...
UIServices.SetBusyState();
DoProcessing();
...
Run Code Online (Sandbox Code Playgroud)

这将自动将光标更改为在应用程序繁忙时等待光标并在空闲时恢复正常.

  • 我不确定为什么人们会低估这个答案.我今天得到了6个downvotes没有任何评论,并且在发布后一年半之后也是如此?至少留下评论,以便我可以改进它. (2认同)

小智 12

一个非常简单的方法是简单地绑定到窗口(或任何其他控件)的'Cursor'属性.例如:

XAML:

<Window
    x:Class="Example.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     Cursor="{Binding Cursor}" />
Run Code Online (Sandbox Code Playgroud)

ViewModel Cursor属性(使用Apex.MVVM):

    private NotifyingProperty cursor = new NotifyingProperty("Cursor", typeof(System.Windows.Input.Cursor), System.Windows.Input.Cursors.Arrow);
    public System.Windows.Input.Cursor Cursor
    {
        get { return (System.Windows.Input.Cursor)GetValue(cursor); }
        set { SetValue(cursor, value); }
    }
Run Code Online (Sandbox Code Playgroud)

然后只需在需要时更改视图中的光标...

    public void DoSomethingLongCommand()
    {
        Cursor = System.Windows.Input.Cursors.Wait;

        ... some long process ...

        Cursor = System.Windows.Input.Cursors.Arrow;
    }
Run Code Online (Sandbox Code Playgroud)


zar*_*zar 8

您想bool在视图模型中拥有一个属性。

    private bool _IsBusy;
    public bool IsBusy 
    {
        get { return _IsBusy; }
        set 
        {
            _IsBusy = value;
            NotifyPropertyChanged("IsBusy");
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在您想要设置要绑定到它的窗口样式。

<Window.Style>
    <Style TargetType="Window">
        <Setter Property="ForceCursor" Value="True"/>
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsBusy}" Value="True">
                <Setter Property="Cursor" Value="Wait"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Style>
Run Code Online (Sandbox Code Playgroud)

现在,每当执行命令并且您的视图模型很忙时,它只会设置标志IsBusy并在完成后重置它。窗口将自动显示等待光标并在完成后恢复原始光标。

您可以在视图模型中编写命令处理程序函数,如下所示:

    private void MyCommandExectute(object obj) // this responds to Button execute
    {
        try
        {
            IsBusy = true;

            CallTheFunctionThatTakesLongTime_Here();
        }
        finally
        {
            IsBusy = false;
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的提示,我将它添加到基类中,它似乎工作正常 - 但前提是 CallTheFunctionThatTakesLongTime_Here() 是异步的。 (2认同)