using System;
using System.ComponentModel;
using System.Diagnostics;
using Developpez.Dotnet.Windows.Service;
namespace Developpez.Dotnet.Windows.ViewModel
{
///
/// Classe de base pour toutes les classes ViewModel (Vue-Modèle) dans le cadre du pattern MVVM
/// Fournit le support pour la notification de changement des propriétés (interface INotifyPropertyChanged)
/// et propose une propriété DisplayName. Cette classe est abstraite.
///
/// Cette classe a été proposée par Josh Smith dans son article sur le pattern MVVM.
public abstract class ViewModelBase : IDisposable, INotifyPropertyChanged
{
#region Constructeur
///
/// Crée une nouvelle instance de ViewModelBase. Ce constructeur est protégé et ne peut
/// être appelé que par les classes dérivées.
///
protected ViewModelBase()
{
}
#endregion // Constructeur
#region Propriétés publiques
///
/// Renvoie le nom convivial de cet objet.
/// Les classes dérivées peuvent affecter une nouvelle valeur à cette propriété,
/// ou modifier son implémentation pour déterminer la valeur à la demande
///
public virtual string DisplayName
{
get;
protected set;
}
#endregion // Propriétés publiques
#region Utilitaires de débogage
///
/// Avertit le développeur si cet objet n'a pas de propriété avec le nom spécifié.
/// Cette méthode n'existe pas en version Release.
///
/// Nom de la propriété
[Conditional("DEBUG")]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
// Vérifie que le nom de propriété correspond à une vraie
// propriété publique d'instance de l'objet
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Nom de propriété incorrect: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
///
/// Indique si une exception doit être levée, ou si Debug.Fail est utilisé quand
/// un nom de propriété incorrect est passé à la méthode VerifyPropertyName.
/// La valeur par défaut est false, mais les classes dérivées peuvent modifier ce
/// comportement.
///
public virtual bool ThrowOnInvalidPropertyName
{
get;
protected set;
}
#endregion // Utilitaires de débogage
#region Membres de INotifyPropertyChanged
///
/// Se produit quand la valeur d'une propriété de cet objet est modifiée
///
public event PropertyChangedEventHandler PropertyChanged;
///
/// Déclenche l'évènement PropertyChanged sur cet objet.
///
/// La propriété dont la valeur a changé
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // Membres de INotifyPropertyChanged
#region Membres de IDisposable
///
/// Appelé pour libérer les ressources liées à cet objet
///
public void Dispose()
{
this.OnDispose();
}
///
/// Les classes dérivées peuvent redéfinir cette méthode pour effectuer
/// des opérations de nettoyage, comme la suppression de gestionnaires d'évènement
///
protected virtual void OnDispose()
{
}
#if DEBUG
///
/// Utile pour vérifier que les objets ViewModel sont correctement ramassés par le
/// garbage collector.
///
~ViewModelBase()
{
string msg = string.Format("{0} ({1}) ({2}) Finalized", this.GetType().Name, this.DisplayName, this.GetHashCode());
System.Diagnostics.Debug.WriteLine(msg);
}
#endif
#endregion // Membres de IDisposable
#region GetService
///
/// Renvoie le service du type spécifié avec le nom spécifié
///
/// Type du service
/// Nom du service
/// Le service demandé s'il existe. Sinon, une ServiceNotFoundException est levée.
public virtual TService GetService(string name)
{
return ServiceLocator.Instance.GetService(name);
}
///
/// Renvoie le service sans nom du type spécifié
///
/// Type du service
/// Le service demandé s'il existe. Sinon, une ServiceNotFoundException est levée.
public TService GetService()
{
return GetService(null);
}
#endregion
}
///
/// Classe de base pour un ViewModel qui expose le modèle via une propriété fortement typée
///
/// Type du modèle
public abstract class ViewModelBase : ViewModelBase
{
///
/// Renvoie le modèle lié à ce ViewModel
///
public TModel Model { get; protected set; }
}
}