namespace GalaSoft.MvvmLight.Messaging
{
using System;
/// <summary>
/// Use this class to send a message when the busy state of an application changes.
/// </summary>
public class BusyMessage : MessageBase
{
/// <summary>
/// Initializes a new instance of the <see cref="BusyMessage"/> class.
/// </summary>
/// <param name="isBusy"><b>true</b> if the application is busy; otherwise, <b>false</b>.</param>
/// <param name="userState">Optional. User state information to include with the message.</param>
public BusyMessage(bool isBusy, object userState)
: this(isBusy, userState, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BusyMessage"/> class.
/// </summary>
/// <param name="isBusy"><b>true</b> if the application is busy; otherwise, <b>false</b>.</param>
/// <param name="userState">Optional. User state information to include with the message.</param>
/// <param name="sender">Optional. The message's original sender.</param>
public BusyMessage(bool isBusy, object userState, object sender)
: base(sender)
{
this.IsBusy = isBusy;
this.UserState = userState;
}
/// <summary>
/// Gets a value indicating whether the application is currently in a busy state.
/// </summary>
public bool IsBusy { get; private set; }
/// <summary>
/// Gets user state information to include with the message.
/// </summary>
public object UserState { get; private set; }
}
}
namespace GalaSoft.MvvmLight.Threading
{
using System;
using System.Threading;
using GalaSoft.MvvmLight.Messaging;
/// <summary>
/// Provides a thread-safe controller for managing the busy state of the application.
/// </summary>
public class BusyController : GalaSoft.MvvmLight.ObservableObject
{
private readonly object SyncRoot = new object();
private int count;
/// <summary>
/// Initializes static members of the <see cref="BusyController"/> class.
/// </summary>
static BusyController()
{
_default = new BusyController();
}
/// <summary>
/// Initializes a new instance of the <see cref="BusyController"/> class.
/// </summary>
public BusyController()
: this(Messenger.Default)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BusyController"/> class.
/// </summary>
/// <param name="messenger">Optional. An <see cref="IMessenger"/> which will be used to send messages.</param>
public BusyController(IMessenger messenger)
{
this.MessengerInstance = messenger;
}
private static BusyController _default;
/// <summary>
/// Gets the default busy controller instance.
/// </summary>
public static BusyController Default
{
get
{
return _default;
}
}
private bool _isBusy;
/// <summary>
/// Gets a value indicating whether the controller is currently in the busy state.
/// </summary>
public bool IsBusy
{
get
{
return this._isBusy;
}
private set
{
if (this._isBusy != value)
{
this._isBusy = value;
this.RaisePropertyChanged(() => this.IsBusy);
}
}
}
private IMessenger _messengerInstance;
/// <summary>
/// Gets the messenger instance used by the controller.
/// </summary>
protected IMessenger MessengerInstance
{
get
{
return this._messengerInstance;
}
set
{
if (this._messengerInstance != value)
{
this._messengerInstance = value;
this.RaisePropertyChanged(() => this.MessengerInstance);
}
}
}
/// <summary>
/// Resets the controller.
/// </summary>
public void Reset()
{
lock (this.SyncRoot)
{
this.IsBusy = false;
this.count = 0;
if (this.MessengerInstance != null)
{
// Send the message indicating that the controller is no longer busy.
this.MessengerInstance.Send<BusyMessage>(new BusyMessage(this.IsBusy, null));
}
}
}
/// <summary>
/// Sends the message.
/// </summary>
/// <param name="value"><b>true</b> if the application is busy; otherwise, <b>false</b> when the application is no longer busy.</param>
public void SendMessage(bool value)
{
this.SendMessage(value, null);
}
/// <summary>
/// Sends the message.
/// </summary>
/// <param name="value"><b>true</b> if the application is busy; otherwise, <b>false</b> when the application is no longer busy.</param>
/// <param name="state">Optional. User state data to include with the message if the controller transitions between busy states.</param>
public void SendMessage(bool value, object userState)
{
lock (this.SyncRoot)
{
bool send = false;
if (value)
{
Interlocked.Increment(ref this.count);
if (this.count == 1)
{
this.IsBusy = true;
// The controller is now busy, send the message.
send = true;
}
}
else
{
if (this.count > 0)
{
Interlocked.Decrement(ref this.count);
if (this.count == 0)
{
this.IsBusy = false;
// The controller is no longer busy, send the message.
send = true;
}
}
}
if (send && this.MessengerInstance != null)
{
this.MessengerInstance.Send<BusyMessage>(new BusyMessage(this.IsBusy, userState, this));
}
}
}
}
}