Usar interfaces con Commands
Problema
Necesito acceder a las propiedades de un control, (por ejemplo, borrar el contenido de un TextBox), y uso (que va a ser que si) un [Command] independiente en una clase (es decir, no escribo el [Command] en el modelo-vista), lo que ocurre es que al hacer el Binding, tengo que pasar a través del parámetro [CommandParameter] el objeto completo, es decir, el TextBox, el botón u lo que sea,
En este caso: dentro del command escribiré la siguiente función [Execute]:
''' <summary>
''' Esta función Borra todo el texto de un textBox pasado por parámetro
''' </summary>
Private Sub cmdExecute(ByVal parameter As Object)
If parameter IsNot Nothing Then
Dim target As TextBox = TryCast(parameter, TextBox)
If target IsNot Nothing Then
If target.Text.Length > 0 Then
target.Clear()
End If
End If
End If
End Sub
Observa que lo primero que hago, es comprobar que el valor del parámetro no sea Nothing, de esta forma evito errores tontos.
Después convierto el [Objeto] en un [TextBox], y por ultimo uso la propiedad del control que me interesa, en este caso la de borrar el contenido del texto.
Entonces… ¿Dónde está el problema?
Pues que cuando diseño controles de usuario, para aplicar un [Command] necesito pasar TODO el control de usuario para hacer el casting.
Supongamos que diseño un control con un cuadro de texto multi-línea y varios botones, para mostrar (por ejemplo) poesías de una forma determinada, otro control para mostrar textos cifrados, etc. Si quiero usar un Command que borre el cuadro de texto del control deberé escribir un Command para cada uno de los controles, y siendo una operación tan sencilla y común (como borrar un cuadro de texto) debería poder hacerse con un único Command.
Después de darle muchas vueltas me he dado cuenta de que puedo usar interfaces con lo que el código se generaliza y puedo reutilizarlo
Ejemplo la siguiente interfaz define dos métodos muy usados en los cuadro de texto, y por lo tanto en todos los controles que tengan cuadros de texto como componente principal
''' <summary>
''' Interface para ser usada por controles compuestos
''' que quieran usar las clases Command
''' </summary>
Public Interface IControlCommand
''' <summary>
''' Obtiene establece la propiedad [Text] del
''' cuadro de texto del control
''' </summary>
Property ZText As String
''' <summary>
''' Limpia [borra], el contenido del cuadro
''' de texto del control
''' </summary>
Sub ZClear()
End Interface
Nota.: el que las propiedades tengan la letra zeta [Z ]delante es para poder distinguirlas rápidamente en el diseñador, y además, sane todas juntas y al final de todo :-)
En el control compuesto que estoy escribiendo, implementare la Interfaz
Imagen del control compuesto que tiene varios controles internos y una funcionalidad definida
Public Class UserControlPrueba
Implements IControlCommand
Public Property ZText As String Implements IControlCommand.ZText
Get
Return Me.TextBoxInterno.Text
End Get
Set(value As String)
Me.TextBoxInterno.Text = value
End Set
End Property
Public Sub ZClear() Implements IControlCommand.ZClear
Me.TextBoxInterno.Clear()
End Sub
End Class
Y la clase Command que borraría el cuadro de texto del control quedaría así:
''' <summary>
''' Borra el contenido de un TextBox
''' </summary>
Public NotInheritable Class ControlClearTextBoxCommand
Inherits DelegateCommand
Implements IDisposable
Public Property LocalGesture As KeyGesture
Public Sub New()
MyBase.New()
'-------------------------------
' Los parametros de [Commnad]
' El [Delegado] (la Accion) que llamara al metodo [cmdExecute]
Dim localExcuteAction As Action(Of Object) =
New Action(Of Object)(AddressOf Me.cmdExecute)
' El [Delegado] que llamara al metodo [cmdCanExecute]
Dim localCanExecuteAction As Predicate(Of Object) =
Function(param) Me.cmdCanExecute(param)
' el nombre de este command
Dim localNombreCommand As String = "TextBoxBorraTextoCommand"
' Juego de teclas que activan el comando (P.e: Ctrl + D)
LocalGesture = New KeyGesture(Key.D, ModifierKeys.Control, "Borrar [Ctrl+D]")
'-------------------------------
MyBase._nombreCommand = localNombreCommand
MyBase._executeAction = localExcuteAction
MyBase._canExecuteAction = localCanExecuteAction
End Sub
''' <summary>
''' Esta funcion Borra todo el texto de un textBox pasado por parametro
''' </summary>
Private Sub cmdExecute(ByVal parameter As Object)
If parameter IsNot Nothing Then
Dim target As IControlCommand = TryCast(parameter, IControlCommand)
'target.TextBoxInterno.Clear()
target.ZText = String.Empty
End If
End Sub
''' <summary>
''' Esta funcion Comprueba que en TextBox haya un texto
''' para poder ejecutar la funcion [Execute]
''' Si hay un texto devuelve (True) [Si se puede ejecutar],
''' si no hay texto devuelve false [No se puede ejecutar]
''' </summary>
Private ReadOnly Property cmdCanExecute(ByVal parameter As Object) As Boolean
Get
Dim resultado As Boolean = False
If parameter IsNot Nothing Then
Dim target As IControlCommand = TryCast(parameter, IControlCommand)
If target IsNot Nothing Then
If target.ZText.Length > 0 Then
resultado = True
End If
End If
End If
Return resultado
End Get
End Property
#Region "IDisposable Support"
Private _disposedValue As Boolean ' Para detectar llamadas redundantes
' IDisposable
Protected Overloads Sub Dispose(disposing As Boolean)
If Not Me._disposedValue Then
If disposing Then
MyBase.Dispose()
End If
End If
Me._disposedValue = True
End Sub
#End Region
End Class
Por último el código XAML del formulario que contiene el control y un botón que borra el cuadro de texto interno del control seria así:
<Window
x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfPruebaEnlaceControlesUsuario"
Title="MainWindow" Height="313" Width="246">
<Window.Resources>
<local:ControlClearTextBoxCommand x:Key=" ControlClearTextBoxCommandResources " />
</Window.Resources>
<Grid>
<local:UserControlPrueba x:Name="UCPrueba"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10"/>
<Button x:Name="ButtonBorrarForm" Content="Button"
HorizontalAlignment="Center" VerticalAlignment="Bottom"
Margin="10" Width="75"
Command="{Binding Mode=OneWay,
Source={StaticResource ControlClearTextBoxCommandResources }}"
CommandParameter="{Binding ElementName=UCPrueba,
Mode=OneWay,
ValidatesOnNotifyDataErrors=False}"
CommandTarget="{Binding ElementName=UCPrueba,
Mode=OneWay,
ValidatesOnNotifyDataErrors=False}" />
</Grid>
</Window>
Imagen del formulario antes y después de pulsar el botón mostrando que el command funciona :-) usando interfaces
|
|
© 1997 - - La Güeb de Joaquín | |||||
Joaquín Medina Serrano
|
|||||
|
Codificación | |
Fecha de creación | |
Última actualización | |
![]() |