Le contrôle ScrollBar de Silverlight ne désactive pas les boutons des ScrollBars lorsque le curseur arrive à une extrémité.
Ce design n’est en général pas satisfaisant dès l’instant ou on veut faire une application un peu jolie et ergonomique.
Pour activer ce comportement sur une ScrollBar, il faut éditer son template et utiliser la classe ScrollBarExtensions. Dans le Template nous commençons par activer la classe d’extensions sur la ScrollBar. Sur n’importe quel élément du template il suffit de déclarer l’AttachedProperty suivante:
Une fois initialisée, la classe d’extensions calcule si la valeur est différente du Minimum ou Maximum et pose deux AttachedProperty sur la ScrollBar : CanIncrease et CanDecrease. Il ne reste plus en suite qu’à Binder les propriété IsEnabled des boutons à ces valeurs.
/// <summary>
/// Provide behavior extensions to a ScrollBar control. When registered add CanIncrease and CanDecrease attached property
/// </summary>
public static class ScrollBarExtensions
{
/// <summary>
/// Get the epsillon value arround the Maximum or Minimum value that activate or deactive the CanIncrease and CanDecrease property
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static double GetEpsillon(DependencyObject obj)
{
return (double)obj.GetValue(EpsillonProperty);
}
/// <summary>
/// Set the epsillon value arround the Maximum or Minimum value that activate or deactive the CanIncrease and CanDecrease property
/// </summary>
/// <param name="obj"></param>
/// <param name="value"></param>
public static void SetEpsillon(DependencyObject obj, double value)
{
obj.SetValue(EpsillonProperty, value);
}
// Using a DependencyProperty as the backing store for Epsillon. This enables animation, styling, binding, etc...
public static readonly DependencyProperty EpsillonProperty =
DependencyProperty.RegisterAttached("Epsillon", typeof(double), typeof(ScrollBarExtensions), new PropertyMetadata(0.001d));
/// <summary>
/// Get the registered ScrollBar
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static ScrollBar GetRegisterScrollbar(DependencyObject obj)
{
return (ScrollBar)obj.GetValue(RegisterScrollbarProperty);
}
/// <summary>
/// Register a ScrollBar
/// </summary>
/// <param name="obj"></param>
/// <param name="value"></param>
public static void SetRegisterScrollbar(DependencyObject obj, ScrollBar value)
{
obj.SetValue(RegisterScrollbarProperty, value);
}
public static readonly DependencyProperty RegisterScrollbarProperty =
DependencyProperty.RegisterAttached("RegisterScrollbar", typeof(ScrollBar), typeof(ScrollBarExtensions), new PropertyMetadata(RegisterScrollbarChangedCallback));
private static void RegisterScrollbarChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var sb = (ScrollBar)e.OldValue;
if (sb != null)
{
sb.ValueChanged -= storyBoardPropertyChanged;
sb.RemoveChangedHandler("Maximum", storyBoardDependecyPropertyChanged);
sb.RemoveChangedHandler("Minimum", storyBoardDependecyPropertyChanged);
}
sb = (ScrollBar)e.NewValue;
if (sb != null)
{
sb.ValueChanged += storyBoardPropertyChanged;
sb.AddChangedHandler("Maximum", storyBoardDependecyPropertyChanged);
sb.AddChangedHandler("Minimum", storyBoardDependecyPropertyChanged);
RefreshValue(sb);
}
}
private static void RefreshValue(ScrollBar sb)
{
var epsillon = GetEpsillon(sb);
SetCanDecrease(sb, (sb.Value - sb.Minimum) > epsillon);
SetCanIncrease(sb, (sb.Maximum - sb.Value) > epsillon);
}
static void storyBoardDependecyPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
{
RefreshValue((ScrollBar)sender);
}
static void storyBoardPropertyChanged(object sender, EventArgs e)
{
RefreshValue((ScrollBar)sender);
}
/// <summary>
/// true when the Value of a ScrollBar is greater than the Minimum + the Epsillon value
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static bool GetCanDecrease(DependencyObject obj)
{
return (bool)obj.GetValue(CanDecreaseProperty);
}
public static void SetCanDecrease(DependencyObject obj, bool value)
{
obj.SetValue(CanDecreaseProperty, value);
}
public static readonly DependencyProperty CanDecreaseProperty =
DependencyProperty.RegisterAttached("CanDecrease", typeof(bool), typeof(ScrollBarExtensions), null);
/// <summary>
/// true when the Value of a ScrollBar is loawer than the Maximum - the Epsillon value
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static bool GetCanIncrease(DependencyObject obj)
{
return (bool)obj.GetValue(CanIncreaseProperty);
}
public static void SetCanIncrease(DependencyObject obj, bool value)
{
obj.SetValue(CanIncreaseProperty, value);
}
public static readonly DependencyProperty CanIncreaseProperty =
DependencyProperty.RegisterAttached("CanIncrease", typeof(bool), typeof(ScrollBarExtensions), null);
}