如何在应用程序shell中实现忙碌指示器 [英] How to implement busy indicator in application shell

查看:77
本文介绍了如何在应用程序shell中实现忙碌指示器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的应用程序的外壳"中实现来自 WPF 扩展工具包的繁忙指示器.目标是在一个地方实现指标,然后能够从任何地方设置 IsBusy 属性,以便它可以被初始化.这是我的外壳:

I am trying to implement the busy indicator from the WPF Extended Toolkit in my application's "shell." The goal is to implement the indicator in one place and then be able to set the IsBusy property from anywhere so that it can be initialized. Here is my shell:

<Window x:Class="Foundation.Shell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:Library.Controls.Views;assembly=Library"
    xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
    WindowStyle="None"
    AllowsTransparency="False"
    Name="ShellView"
    FontFamily="Yu Gothic Light"
    Background="{StaticResource AiWhiteBrush}">

<!--Region Outer Most Grid-->
<xctk:BusyIndicator IsBusy="{Binding IsBusy}">
    <Grid x:Name="OuterGrid">

<!-- CONTENT HERE -->

    </Grid>
</xctk:BusyIndicator>
<!--End Region-->

然后,我的 Shell 的 ViewModel 看起来像这样:

Then, my Shell's ViewModel looks like this:

using CashDrawer.Views;
using Library.BaseClasses;
using Library.StaticClasses;
using Microsoft.Practices.Prism.Commands;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using WpfPageTransitions;

namespace Foundation
{
    public class ShellViewModel : ViewModelBase
    {
        #region constructor(s)

        public ShellViewModel()
        {
            StateManager.IsBusyChange += new StateManager.IsBusyHandler(IsBusyEventAction);
        }

        #endregion constructor(s)

        #region properties

        private bool _IsBusy;
        public bool IsBusy
        {
            get
            {
                return _IsBusy;
            }
            set
            {
                if (_IsBusy != value)
                {
                    _IsBusy = value;
                    OnPropertyChanged("IsBusy");
                }
            }
        }

        #endregion properties

        #region actions, functions, and methods

        private void IsBusyEventAction(object sender, EventArgs e)
        {
            if (StateManager.IsBusy)
            {
                this.IsBusy = true;
            }
            else
            {
                this.IsBusy = false;
            }
        }

        #endregion actions, functions, and methods
    }
}

最后,我创建了一个静态的 StateManager 类:

Last, I have created a static StateManager class:

using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using WpfPageTransitions;

namespace Library.StaticClasses
{
    public static class StateManager
    {

        private static bool _IsBusy;
        public static bool IsBusy
        {
            get
            {
                return _IsBusy;
            }
            set
            {
                if (_IsBusy != value)
                {
                    _IsBusy = value;
                    IsBusyChange(null, null);
                }
            }
        }

        public delegate void IsBusyHandler(object sender, EventArgs e);

        public static event IsBusyHandler IsBusyChange;
    }
}

这个想法是,当 StateManager 的 IsBusy 属性改变时,它会触发一个事件,相应地改变 ShellViewModel 中的 IsBusy 属性.逻辑运行良好.但是,忙碌指示器没有按预期工作.这是来自另一个视图模型的代码片段,用于切换 IsBusy 属性:

The idea is that when the StateManager's IsBusy property is changed, it will fire an event that will change the IsBusy property in the ShellViewModel accordingly. The logic is working fine. However, the busy indicator isn't working as expected. Here is a code snippet from another view model that switches the IsBusy property:

private void SaveCommand_Action()
{
     StateManager.IsBusy = true;

     this.Validate();

     if (!HasValidationErrors)
     {
        if (this.CustomerControlVM.SaveCustomer() != 0)
        {
            VehicleControlVM.VehicleModel.CustomerID = this.CustomerControlVM.CustomerModel.CustomerID;
            this.VehicleControlVM.SaveVehicle();

            ComplaintsView complaintsControl = new ComplaintsView();

            (complaintsControl.DataContext as ComplaintsViewModel).CurrentVehicle = this.VehicleControlVM.VehicleModel;
            (complaintsControl.DataContext as ComplaintsViewModel).CurrentCustomer = this.CustomerControlVM.CustomerModel;
            StateManager.LoadView(complaintsControl, PageTransitionType.SlideLeft);
        }
    }

    StateManager.IsBusy = false;
}

我看到代码有些滞后,但我从未看到过忙指示符出现.我可以删除 StateManager.IsBusy = false; 并且忙碌指示器将出现(当然并且无限期显示.)我尝试在 IsBusy 状态更改之间创建更长的延迟,但指示器仍然没有出现.我已经阅读了多篇文章和文章,试图了解可能出了什么问题,但我没有看到任何有用的信息.我知道 IsBusy 指示器发生在 UI 线程上,但我正在更改不应在 UI 线程上的 ViewModel 中的 IsBusy 状态.有什么想法或建议吗?

I am seeing some lag in the code, but I never see the busy indicator appear. I can remove StateManager.IsBusy = false; and the busy indicator will appear (and show indefinitely of course.) I have tried creating a longer delay between the IsBusy state changes and the indicator still doesn't appear. I have read multiple posts and articles trying to understand what may be going wrong but I am not seeing anything helpful. I am aware that the IsBusy indicator is happening on the UI thread, but I am changing the IsBusy states in the ViewModel which should not be on the UI thread. Any thoughts or suggestions?

推荐答案

关于我最后的评论.

您可以更改 statemanager 以执行操作,因此您传入方法,状态管理器可以设置调用等

You could change the statemanager to take in an action instead, so you pass in the method, and the state manager can setup the invoke etc

public static class StateManager 
{

public static void Process(Action action) {
    IsBusy = true;
    Application.Current.Dispatcher.Invoke(action, System.Windows.Threading.DispatcherPriority.Background);
    IsBusy = false;
}

private static bool _IsBusy;
public static bool IsBusy {
    get {
        return _IsBusy;
    }
    set {
        if (_IsBusy != value) {
            _IsBusy = value;
            IsBusyChange(null, null);
        }
    }
}

public delegate void IsBusyHandler(object sender, EventArgs e);

public static event IsBusyHandler IsBusyChange;

}

然后你可以这样做:

private void SaveCommand_Action()
{
     StateManager.Process(() =>
     {

     this.Validate();

     if (!HasValidationErrors)
     {
        if (this.CustomerControlVM.SaveCustomer() != 0)
        {
            VehicleControlVM.VehicleModel.CustomerID = this.CustomerControlVM.CustomerModel.CustomerID;
            this.VehicleControlVM.SaveVehicle();

            ComplaintsView complaintsControl = new ComplaintsView();

            (complaintsControl.DataContext as ComplaintsViewModel).CurrentVehicle = this.VehicleControlVM.VehicleModel;
            (complaintsControl.DataContext as ComplaintsViewModel).CurrentCustomer = this.CustomerControlVM.CustomerModel;
            StateManager.LoadView(complaintsControl, PageTransitionType.SlideLeft);
        }
    }

    StateManager.IsBusy = false;
});
}

这篇关于如何在应用程序shell中实现忙碌指示器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆