Eventos

[WPF & SL] Behavior


Aveces los comportamientos básicos de los controles no siempre satisfacen todos nuestros requerimientos. Digamos por ejemplo que en nuestra aplicación WPF queremos que nuestros TextBox solo acepten números, lo peor que podríamos hacer en este tipo de casos es manejar el evento PreviewTextInput en el codebehind de cada vista de nuestra aplicación porque simplemente resultaría poco casi nada mantenible.

Entonces en esta ocasión vamos a solucionar este tema usando Behavior, que simplemente es la clase base que nos permitirá adjuntar comportamientos. Para empezar lo primero que debemos hacer es agregar una referencia a System.Windows.Interactivity y luego crear nuestra clase que extenderá Behavior<T>.


Como podemos apreciar en la presente imagen, la clase abstracta Behavior tiene la propiedad AssociatedObject, la cual es la que tendrá la referencia al control adjunto y dos métodos virtual, los cuales tenemos que sobrescribir para implementar correctamente Behavior. Si quieres más detalle sobre Behavior, aquí.

Ahora luego de construir nuestra clase de ejemplo ValueTypeBehavior tenemos algo como esto:


namespace WPF.SimpleBehavior.Behaviors
{
    public class ValueTypeBehavior : Behavior<UIElement>
    {
        protected override void OnAttached()
        {
            this.AssociatedObject.PreviewTextInput += AssociatedObject_PreviewTextInput;
            base.OnAttached();
        }

        protected override void OnDetaching()
        {
            this.AssociatedObject.PreviewTextInput -= AssociatedObject_PreviewTextInput;
            base.OnDetaching();
        }

        private void AssociatedObject_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
        {
            int integer;
            e.Handled = !int.TryParse(e.Text, out integer);
        }
    }
}
Como se puede ver la implementación es muy sencilla, en este caso estamos manejando un evento pero puede ser cualquier otra cosa, se puede enviar información a través de un servicio, escribir en un log, etc. Para darle un poco más de funcionalidad le vamos a agregar un Dependency Property y ahora quedaria así:
namespace WPF.SimpleBehavior.Behaviors
{
    public class ValueTypeBehavior : Behavior<UIElement>
    {
        public ValueType ValueType
        {
            get { return (ValueType)GetValue(ValueTypeProperty); }
            set { SetValue(ValueTypeProperty, value); }
        }

        public static readonly DependencyProperty ValueTypeProperty =
            DependencyProperty.Register("ValueType", typeof(ValueType), typeof(ValueTypeBehavior), new PropertyMetadata(ValueType.String));

        protected override void OnAttached()
        {
            this.AssociatedObject.PreviewTextInput += AssociatedObject_PreviewTextInput;
            base.OnAttached();
        }

        protected override void OnDetaching()
        {
            this.AssociatedObject.PreviewTextInput -= AssociatedObject_PreviewTextInput;
            base.OnDetaching();
        }

        private void AssociatedObject_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
        {
            switch (ValueType)
            {
                case ValueType.String:
                    break;
                case ValueType.Int32:
                    int integer;
                    if (!int.TryParse(e.Text, out integer))
                        e.Handled = true;
                    break;
                default:
                    break;
            }
        }
    }

    public enum ValueType
    {
        String = 0,
        Int32 = 1
    }
}
Ahora lo último que falta es modificar nuestro XAML para poder usarlo, lo único que tenemos que hacer es agregar una referencia a System.Windows.Interactivity y a nuestra clase que en este caso solo serían xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" y xmlns:b="clr-namespace:WPF.SimpleBehavior.Behaviors" respectivamente. Ahora quedaría algo así:
<Window x:Class="WPF.SimpleBehavior.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:b="clr-namespace:WPF.SimpleBehavior.Behaviors"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        Title="WPF - SimpleBehavior" Height="350" Width="525">

    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Text="My age is:" FontSize="72" Margin="9" FontFamily="Segoe UI Light" Foreground="Orange"/>
        <TextBox FontSize="72" Margin="9" TextAlignment="Center">
            <i:Interaction.Behaviors>
                <b:ValueTypeBehavior ValueType="Int32" />
            </i:Interaction.Behaviors>
        </TextBox>
        <TextBlock Text="xamldevelopment.blogspot.com" TextAlignment="Center" FontSize="21" Margin="9" FontFamily="Segoe UI Light" Foreground="Orange"/>
    </StackPanel>
</Window>

Y listo!

Cabe indicar que se puede agregar más de un Behavior, solo se tendrían que ir colocando dentro de las etiquetas <i:Interaction.Behaviors> y </i:Interaction.Behaviors>.

El evento PreviewTextInput solo esta disponible para WPF, en Silverlight tendrías que usar KeyDown.

Actualmente la clase Behavior no existe naturalmente para WinRT.


No hay comentarios.:

Publicar un comentario

Epicalsoft — Superheroic Software Development Blog Designed by Templateism.com Copyright © 2014

Con tecnología de Blogger.