using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Markup;
namespace Developpez.Dotnet.Windows.Markup
{
///
/// Implémente une MarkupExtension qui peut mettre à jour sa cible
///
///
/// Pour créer une classe dérivée de UpdatableMarkupExtension , implémentez la méthode ProvideValueInternal .
///
public abstract class UpdatableMarkupExtension : MarkupExtension
{
private readonly List _targetObjects = new List();
private object _targetProperty;
///
/// Fournit la liste des objets cibles de cette markup extension
///
protected IEnumerable TargetObjects
{
get { return _targetObjects; }
}
///
/// Indique la propriété cible de cette markup extension
///
protected object TargetProperty
{
get { return _targetProperty; }
}
///
/// Fournit la valeur de cette markup extension
///
/// Objet qui peut fournir des services pour la markup extension
/// La valeur de cette markup extension
///
/// Cette méthode est scellée et ne peut être redéfinie. Redéfinissez ProvideValueInternal à la place.
///
public sealed override object ProvideValue(IServiceProvider serviceProvider)
{
// Retrieve target information
IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (target != null && target.TargetObject != null)
{
// In a template the TargetObject is a SharedDp (internal WPF class)
// In that case, the markup extension itself is returned to be re-evaluated later
if (target.TargetObject.GetType().FullName == "System.Windows.SharedDp")
return this;
// Save target information for later updates
_targetObjects.Add(target.TargetObject);
_targetProperty = target.TargetProperty;
}
// Delegate the work to the derived class
return ProvideValueInternal(serviceProvider);
}
///
/// Met à jour les cibles de la markup extension avec la valeur spécifiée
///
/// La nouvelle valeur pour les cibles de la markup extension
protected virtual void UpdateValue(object value)
{
if (_targetObjects.Count > 0)
{
// Update the target property of each target object
foreach (var target in _targetObjects)
{
if (_targetProperty is DependencyProperty)
{
DependencyObject obj = (DependencyObject)target;
DependencyProperty prop = (DependencyProperty)_targetProperty;
Action updateAction = () => obj.SetValue(prop, value);
// Check whether the target object can be accessed from the
// current thread, and use Dispatcher.Invoke if it can't
if (obj.CheckAccess())
updateAction();
else
obj.Dispatcher.Invoke(updateAction);
}
else if (_targetProperty is PropertyInfo)
{
PropertyInfo prop = (PropertyInfo)_targetProperty;
prop.SetValue(target, value, null);
}
}
}
}
///
/// Fournit la valeur de cette markup extension
///
/// Objet qui peut fournir des services pour la markup extension
/// La valeur de cette markup extension
///
/// Cette méthode est abstraite et doit être implémentées par les classes dérivées.
///
protected abstract object ProvideValueInternal(IServiceProvider serviceProvider);
}
}