Je vais vous montrer dans cet article comment ajouter un nouveau comportement à un contrôle WPF en utilisant un Behavior.
Description
Dans l’exemple ci-dessous nous allons ajouter une propriété à une TextBox pour qu’elle accepte seulement des caractères alphanumériques.
DependencyProperty
Il nous faut une classe statique avec une DependencyProperty, de façon à avoir une nouvelle propriété accessible dans la vue (XAML), je l’ai appelée IsAlphaNumericInput.
public static readonly DependencyProperty IsAlphaNumericInputProperty = DependencyProperty.RegisterAttached(
"IsAlphaNumericInput",
typeof(bool),
typeof(TextBoxBehavior),
new FrameworkPropertyMetadata(false, OnIsAlphaNumericInputChanged));
Lorsque la propriété IsAlphaNumericInput changera de valeur, la méthode OnIsAlphaNumericInputChanged sera appelée.
Événement
La méthode OnIsAlphaNumericInputChanged permet de vérifier que la propriété est bien sur une TextBox et de récupérer sa valeur.
Si elle est renseignée et qu’elle est à ‘True’ on s’abonne à l’évènement PreviewTextInput de façon à pouvoir contrôler ce que va entrer l’utilisateur.
private static void OnIsAlphaNumericInputChanged(DependencyObject owner, DependencyPropertyChangedEventArgs args)
{
Control textBox = owner as TextBox;
bool? isAlphaNumericInput = args.NewValue as bool?;
if (isAlphaNumericInput == null || textBox == null)
return;
if (isAlphaNumericInput ?? false)
{
textBox.PreviewTextInput += OnAlphaNumericInputPreviewTextInputHandler;
}
else
{
textBox.PreviewTextInput -= OnAlphaNumericInputPreviewTextInputHandler;
}
}
Regex
Pour vérifier que le caractère entré par l’utilisateur est bien un caractère alphanumérique, on va utiliser une expression régulière (Regex).
private static void OnTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
Control control = sender as TextBox;
if (control == null)
return;
if (string.IsNullOrEmpty(e.Text))
return;
Regex r = new Regex("^[a-zA-Z0-9]*$");
e.Handled = !r.IsMatch(e.Text);
}
Utilisation
Pour utiliser notre Behavior, il suffit d’ajouter la propriété IsAlphaNumericInput sur notre TextBox.
<TextBox Grid.Column="0" Grid.Row="0"
local:TextBoxBehavior.IsAlphaNumericInput="True"
Text="{Binding Text}"
Width="200">
Il est bien sûr possible de la Binder sur une propriété de notre ViewModel.
Code complet
namespace SoftFluent
{
public static partial class TextBoxBehavior
{
public static readonly DependencyProperty IsAlphaNumericInputProperty = DependencyProperty.RegisterAttached(
"IsAlphaNumericInput",
typeof(bool),
typeof(TextBoxBehavior),
new FrameworkPropertyMetadata(false, OnIsAlphaNumericInputChanged));
public static bool GetIsAlphaNumericInput(DependencyObject obj)
{
return (bool)obj.GetValue(IsAlphaNumericInputProperty);
}
public static void SetIsAlphaNumericInput(DependencyObject obj, bool value)
{
obj.SetValue(IsAlphaNumericInputProperty, value);
}
private static TextCompositionEventHandler OnAlphaNumericInputPreviewTextInputHandler = new TextCompositionEventHandler(OnTextBox_PreviewTextInput);
private static void OnIsAlphaNumericInputChanged(DependencyObject owner, DependencyPropertyChangedEventArgs args)
{
Control textBox = owner as TextBox;
bool? isAlphaNumericInput = args.NewValue as bool?;
if (isAlphaNumericInput == null || textBox == null)
return;
if (isAlphaNumericInput ?? false)
{
textBox.PreviewTextInput += OnAlphaNumericInputPreviewTextInputHandler;
}
else
{
textBox.PreviewTextInput -= OnAlphaNumericInputPreviewTextInputHandler;
}
}
private static void OnTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
Control control = sender as TextBox;
if (control == null)
return;
if (string.IsNullOrEmpty(e.Text))
return;
Regex r = new Regex("^[a-zA-Z0-9]*$");
e.Handled = !r.IsMatch(e.Text);
}
}
}
<Window x:Class="SoftFluent.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SoftFluent"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Grid.Column="0" Grid.Row="0"
local:TextBoxBehavior.IsAlphaNumericInput="True"
Text="{Binding Text}"
Width="200">
</TextBox>
</Grid>
</Window>
Vous êtes maintenant prêt pour développer vos propres Behaviors.