using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Developpez.Dotnet.Windows.Behaviors
{
///
/// Fournit une indication visuelle d'une erreur de validation sur un contrôle
///
public static class ErrorProvider
{
///
/// Obtient la valeur de la propriété attachée ErrorMessage pour le contrôle
///
/// Contrôle pour lequel on veut obtenir la valeur de la propriété
/// Le message d'erreur associé à ce contrôle
public static string GetErrorMessage(this FrameworkElement obj)
{
return (string)obj.GetValue(ErrorMessageProperty);
}
///
/// Définit la valeur de la propriété attachée ErrorMessage pour le contrôle
///
/// Contrôle pour lequel on définit la valeur de la propriété
/// Le message d'erreur à associer à ce contrôle
public static void SetErrorMessage(this FrameworkElement obj, string value)
{
obj.SetValue(ErrorMessageProperty, value);
}
///
/// Identifiant de la propriété attachée ErrorMessage
///
public static readonly DependencyProperty ErrorMessageProperty =
DependencyProperty.RegisterAttached(
"ErrorMessage",
typeof(string),
typeof(ErrorProvider),
new UIPropertyMetadata(
null,
ErrorMessageChanged));
///
/// Obtient la valeur de la propriété attachée IconSource pour le contrôle
///
/// Contrôle pour lequel on veut obtenir la valeur de la propriété
/// L'icône d'erreur utilisée sur ce contrôle
public static ImageSource GetIconSource(FrameworkElement obj)
{
return (ImageSource)obj.GetValue(IconSourceProperty);
}
///
/// Définit la valeur de la propriété attachée IconSource pour le contrôle
///
/// Contrôle pour lequel on définit la valeur de la propriété
/// L'icône d'erreur à utiliser sur ce contrôle
public static void SetIconSource(FrameworkElement obj, ImageSource value)
{
obj.SetValue(IconSourceProperty, value);
}
///
/// Identifiant de la propriété attachée IconSource
///
public static readonly DependencyProperty IconSourceProperty =
DependencyProperty.RegisterAttached(
"IconSource",
typeof(ImageSource),
typeof(ErrorProvider),
new FrameworkPropertyMetadata(GetDefaultErrorIcon(), FrameworkPropertyMetadataOptions.Inherits));
///
/// Obtient la valeur de la propriété attachée IconHorizontalAlignment pour le contrôle
///
/// Contrôle pour lequel on veut obtenir la valeur de la propriété
/// L'alignement horizontal de l'icône d'erreur
public static HorizontalAlignment GetIconHorizontalAlignment(FrameworkElement obj)
{
return (HorizontalAlignment)obj.GetValue(IconHorizontalAlignmentProperty);
}
///
/// Définit la valeur de la propriété attachée IconHorizontalAlignment pour le contrôle
///
/// Contrôle pour lequel on définit la valeur de la propriété
/// L'alignement horizontal de l'icône d'erreur
public static void SetIconHorizontalAlignment(FrameworkElement obj, HorizontalAlignment value)
{
obj.SetValue(IconHorizontalAlignmentProperty, value);
}
///
/// Identifiant de la propriété attachée IconHorizontalAlignment
///
public static readonly DependencyProperty IconHorizontalAlignmentProperty =
DependencyProperty.RegisterAttached("IconHorizontalAlignment", typeof(HorizontalAlignment), typeof(ErrorProvider), new UIPropertyMetadata(HorizontalAlignment.Right));
///
/// Obtient la valeur de la propriété attachée IconVerticalAlignment pour le contrôle
///
/// Contrôle pour lequel on veut obtenir la valeur de la propriété
/// L'alignement vertical de l'icône d'erreur
public static VerticalAlignment GetIconVerticalAlignment(DependencyObject obj)
{
return (VerticalAlignment)obj.GetValue(IconVerticalAlignmentProperty);
}
///
/// Définit la valeur de la propriété attachée IconVerticalAlignment pour le contrôle
///
/// Contrôle pour lequel on définit la valeur de la propriété
/// L'alignement vertical de l'icône d'erreur
public static void SetIconVerticalAlignment(DependencyObject obj, VerticalAlignment value)
{
obj.SetValue(IconVerticalAlignmentProperty, value);
}
///
/// Identifiant de la propriété attachée IconVerticalAlignment
///
public static readonly DependencyProperty IconVerticalAlignmentProperty =
DependencyProperty.RegisterAttached("IconVerticalAlignment", typeof(VerticalAlignment), typeof(ErrorProvider), new UIPropertyMetadata(VerticalAlignment.Center));
private static void ErrorMessageChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var element = o as FrameworkElement;
if (element == null)
return;
var oldValue = (string)e.OldValue;
var newValue = (string)e.NewValue;
if (!string.IsNullOrEmpty(oldValue) && string.IsNullOrEmpty(newValue))
{
element.DoWhenLoaded(RemoveErrorAdorner);
}
else if (!string.IsNullOrEmpty(newValue) && string.IsNullOrEmpty(oldValue))
{
element.DoWhenLoaded(AddErrorAdorner);
}
}
private static void RemoveErrorAdorner(UIElement uiElement)
{
var layer = AdornerLayer.GetAdornerLayer(uiElement);
if (layer == null)
return;
var adorner = layer.GetAdorners(uiElement).OfType().FirstOrDefault();
if (adorner != null)
layer.Remove(adorner);
}
private static void AddErrorAdorner(UIElement uiElement)
{
var layer = AdornerLayer.GetAdornerLayer(uiElement);
if (layer == null)
return;
var adorner = new ErrorAdorner(uiElement);
layer.Add(adorner);
}
private static ImageSource GetDefaultErrorIcon()
{
return new BitmapImage(
new Uri("pack://application:,,,/Developpez.Dotnet.Windows;component/Images/error.png"));
}
private class ErrorAdorner : Adorner
{
private readonly Border _errorBorder;
public ErrorAdorner(UIElement adornedElement)
: base(adornedElement)
{
_errorBorder = new Border();
_errorBorder.BorderThickness = new Thickness(2);
_errorBorder.BorderBrush = Brushes.Red;
Image img = new Image();
img.Stretch = Stretch.None;
BindToAdornedElement(img, Image.SourceProperty, IconSourceProperty);
BindToAdornedElement(img, ToolTipProperty, ErrorMessageProperty);
BindToAdornedElement(img, HorizontalAlignmentProperty, IconHorizontalAlignmentProperty);
BindToAdornedElement(img, VerticalAlignmentProperty, IconVerticalAlignmentProperty);
_errorBorder.Child = img;
this.AddLogicalChild(_errorBorder);
this.AddVisualChild(_errorBorder);
}
void BindToAdornedElement(FrameworkElement target, DependencyProperty targetProperty, DependencyProperty sourceProperty)
{
Binding binding = new Binding
{
Source = AdornedElement,
Path = new PropertyPath(sourceProperty)
};
target.SetBinding(targetProperty, binding);
}
protected override Size MeasureOverride(Size constraint)
{
AdornedElement.Measure(constraint);
return AdornedElement.RenderSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
_errorBorder.Arrange(new Rect(finalSize));
return finalSize;
}
protected override Visual GetVisualChild(int index)
{
if (index == 0)
return _errorBorder;
throw new ArgumentOutOfRangeException("index");
}
protected override int VisualChildrenCount
{
get
{
return 1;
}
}
protected override System.Collections.IEnumerator LogicalChildren
{
get
{
yield return _errorBorder;
}
}
}
}
}