Wpf - Menu con tres botones

Descripción general

Pequeño estudio de como conjuntar en una ventana Wpf, un menú con tres botones [Aceptar], [Cancelar], [Terminar], manejados mediante Commands, que se activen y desactiven de forma coordinada.

[TOC] Tabla de Contenidos


↑↑↑

Resumen

El resumen en imagenes de lo que hace este codigo, es el siguiente:

Tres botones, situacion inicial
Tres botones, situación datos correctos
Tres botones, situación Boton cancelar activo


↑↑↑

Código xaml de la ventana

   <Window x:Class="WindowTresBotonesCommand"
        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:EmailFotosIneitor2017"
        mc:Ignorable="d"
        Title="Window prueba Tres Botones con Commnad"
        Height="150"  Width="400">



    <Window.Resources>
        <!--El comando personalizado para el botón  [Aceptar, Ejecutar] 
             porque no encuentro ningún [ApplicationCommands] que
             represente la orden de ejecutar un proceso -->
        <RoutedUICommand x:Key="AccionBotonAceptarCmd"
 
                         Text="Acciones que se producen al pulsar el botón aceptar">
        </RoutedUICommand>
    </Window.Resources>

    
    <Window.CommandBindings>
        <!--El comando personalizado para el botón  [Aceptar, Ejecutar]-->
        <CommandBinding Command="{StaticResource AccionBotonAceptarCmd}"  
                        Executed="AccionBotonAceptarCmd_Executed" 
                        CanExecute="AccionBotonAceptarCmd_CanExecute"/>

        <!--los comandos [ApplicationCommands] standard que empleo 
            para los botones cancelar [Stop] y terminar [Close]-->
        <CommandBinding Command="ApplicationCommands.Stop"     
                        Executed="StopCommandBinding_Executed"    
                        CanExecute="StopCommandBinding_CanExecute"/>
        
        <CommandBinding Command="ApplicationCommands.Close"    
                        Executed="CloseCommandBinding_Executed"  
                        CanExecute="CloseCommandBinding_CanExecute"/>
    </Window.CommandBindings>


        <Grid x:Name="GridPrincipalVentana" >
            
            <!-- Definición de filas del Grid principal -->
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"  />
            <RowDefinition Height="*" />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>


        <!-- El menu de la ventana -->
        <DockPanel Grid.Row="0" 
                   x:Name="dockPanelMenu"                     
                   Height="31" Width="Auto"  
                   HorizontalAlignment="Stretch" 
                   VerticalAlignment="Top" 
                   DockPanel.Dock="Top" 
                   LastChildFill="False" 
                   IsEnabled="true" >

            <Menu Name="MenuGeneral" Height="23" Width="Auto" DockPanel.Dock="Top">
                
                <MenuItem Header="_Archivo" x:Name="MenuArchivo">
                    <MenuItem Header="_Aceptar" Name="MenuArchivoAceptar" 
                              Command="{StaticResource AccionBotonAceptarCmd}" />

                    <MenuItem Header="_Terminar" Name="MenuArchivoSalir" 
                              Command="ApplicationCommands.Close" />

                </MenuItem>
                <MenuItem Header="_Editar" x:Name="MenuEditar" />
                <MenuItem Header="_Herramientas" x:Name="MenuHerramientas" />
                <MenuItem Header="_Ayuda" x:Name="MenuAyuda" />
            </Menu>
        </DockPanel>


        <!-- Grid con los tres botones [Aceptar], [Cancelar],[ Terminar] -->
        <Grid  Grid.Row="2" 
               Name="GridPanelTresBotonesOkCancelSalirConCommand" 
               HorizontalAlignment="Right"  
               VerticalAlignment="Bottom" 
               Grid.IsSharedSizeScope="True"               Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="ButtonsAceptarCancelar" Width="120" />
                <ColumnDefinition SharedSizeGroup="ButtonsAceptarCancelar" />
                <ColumnDefinition SharedSizeGroup="ButtonsAceptarCancelar" />

            </Grid.ColumnDefinitions>

            <Button Grid.Column="0"
                    Name="ButtonAceptar"
                    Command="{StaticResource AccionBotonAceptarCmd}"
                    Content="Aceptar" />

            <Button Grid.Column="1"
                    Name="ButtonCancelar"
                    Command="ApplicationCommands.Stop"
                    Content="Cancelar"
                    IsDefault="True" />


            <Button Grid.Column="2"
                    Name="ButtonTerminar"
                    Command="ApplicationCommands.Close"
                    Content="Terminar"
                    IsCancel="True"
                    IsDefault="True" />

        </Grid>


        <!-- Simula todo el proceso de validación de datos correctos de esta ventana wpf-->
        <StackPanel HorizontalAlignment="Center"  Grid.Row="1"  VerticalAlignment="Center" >   
        <RadioButton x:Name="RadioButtonDatosCorrectos" Content="Datos Correctos" 
                     HorizontalAlignment="Center"   VerticalAlignment="Top" 
                     IsChecked="True" Click="RadioButtonDatosCorrectos_Click"/>
        <RadioButton x:Name="RadioButtonDatosErroneos"  Content="Datos Erróneos"  
                     HorizontalAlignment="Center"   VerticalAlignment="Top" 
                     Click="RadioButtonDatosErroneos_Click"/>
        </StackPanel>
    </Grid>
</Window>
    


↑↑↑

Código Visual Basic de la ventana

Public Class WindowTresBotonesCommand


#Region "Acciones Command de los botones de la Ventana"

    '-----------------------------------------------------------
    'NOTA
    '
    'Los botones [Aceptar], [Cancelar], [Terminar] 
    ' se deben comportar de la siguiente manera.
    '
    'En la situación Inicial (cuando se abre por primera vez la ventana wpf)
    'Solo esta activado el botón [Terminar] para poder cerrar la ventana.
    '
    'El botón [Aceptar] se activa cuando el control de entrada de los datos sea correcto, 
    'es decir, Cuando los datos de entrada del formulario son correctos, entonces se activa el botón [Aceptar]. 
    'y entonces, en este momento estarán activados a la vez el botón [Aceptar] y el botón [Terminar]
    ' * El botón [Aceptar]  activo, (unicamente) si los datos de la ventana Wpf, son correctos
    ' * El botón [Cancelar] desactivado 
    ' * El botón [Terminar] activo
    '
    '
    'Una vez activado el botón [Aceptar], el juego de los botones es el siguiente:
    'Al pulsar el botón [Aceptar]
    ' * El botón [Aceptar]  desactivado
    ' * El botón [Cancelar] activado,    para poder detener el proceso iniciado.    
    ' * El botón [Terminar] desactivado
    '
    '
    'Al pulsar el botón [Cancelar]
    ' * El botón [Aceptar]  activo, (Porque en este momento, los datos de la ventana Wpf, son correctos
    ' * El botón [Cancelar] desactivado 
    ' * El botón [Terminar] activo
    ' * Se activa el [Menú] de la ventana
    '
    'Al pulsar el botón [Terminar] se debe cerrar el formulario
    ' por lo que, en principio, no importa el estado de los botones:
    ' pero como hay que ser educado', se dejan los botones en la situación inicial.
    ' * El botón [Aceptar]  activo, (unicamente) si los datos de la ventana Wpf, son correctos
    ' * El botón [Cancelar] desactivado 
    ' * El botón [Terminar] activo
    ' * Se activa el [Menú] de la ventana
    ' * Después se cierra el formulario
    '-----------------------------------------------------------



    '--------------------------------------------------------------
    '--------------------------------------------------------------

    ''' <summary>
    '''   Esta variable se emplea en las funciones [Cmd_Executed] Command Executed, 
    '''   para saber si el botón cancelar esta [Enable], o no.
    '''   He intentado usar directamente al valor [Button.IsEnabled], pero el problema 
    '''   es que desde un command, se puede leer su valor, pero NO PUEDO cambiarlo
    '''   (y no sé porque,) pero lo que sí puedo es cambiar el valor de una 
    '''   variable local de la ventana y consultar su valor en los demás command.
    ''' </summary>
    Private ElBotonCancelarEstaAcivado As Boolean = False



    ''' <summary>
    '''  Activa o desactiva el botón [Cancelar]
    ''' </summary>
    ''' <param name=valor">"
    '''   Un valor Boolean que indica si el botón [Cancelar] 
    '''   esta activado [IsEnabled], si [True], o no [False]
    '''   </param>
    Private Sub ActivarElButonCancel(ByVal valor As Boolean)
        '------------------------------------------------------
        ' desactivación del botón [Cancelar]
        ' No es necesario, se hace en [ StopCommandBinding_CanExecute]
        ' usando el valor de la variable [ElBotonCancelarEstaAcivado]
        '----------------
        ' Desactivación de TODO el menu
        MenuGeneral.IsEnabled = Not (valor)
        '----------------
        ' Bandera para su uso en los command que indica
        ' si el botón  [Cancelar] esta activado o no
        ElBotonCancelarEstaAcivado = valor
    End Sub



    '--------------------------------------------------------------
    '--------------------------------------------------------------
    ' Botón [Aceptar]
    '--------------------------------------------------------------

    ''' <summary>
    ''' Acción a realizar al pulsar el botón [Aceptar]
    ''' </summary>
    Private Sub AccionBotonAceptarCmd_Executed(sender As Object, e As ExecutedRoutedEventArgs)

        '------------------------------------------------------------
        ' Antes de iniciar el proceso se activan los botones
        ' El botón cancelar activo , para pode detenerlo
        ActivarElButonCancel(True)
        '------------------------------------------------------------
        ' Este es el proceso que se realiza al pulsar el botón [Aceptar]
        Dim objBeep As New Microsoft.VisualBasic.Devices.Audio
        objBeep.PlaySystemSound(System.Media.SystemSounds.Beep)
    End Sub


    ''' <summary>
    '''  botón [Aceptar], Puede activarse o no
    ''' </summary>
    Private Sub AccionBotonAceptarCmd_CanExecute(sender As Object, e As CanExecuteRoutedEventArgs)
        '------------------------------------------------------------
        'NOTA
        ' * Uso la variable [ElBotonCancelarEstaAcivado] y la función [ActivarElButonCancel] 
        '   porque desde un command se puede leer el estado [IsEnabled], pero no puedo cambiarlo.
        ' * Sin embargo desde un command se puede cambiar el valor de una variable local de la ventana wpf
        ' * Por construcción, el botón Aceptar solo puede estar [Enabled], cuando el 
        '   botón [Cancelar] esta desactivado [IsEnabled = False], o cuando el control de 
        '   validación de valores de vuelve el valor True, que indica que todos 
        '   los valores de la ventana Wpf, son correctos.
        '------------------------------------------------------------
        If ElBotonCancelarEstaAcivado = True Then
            e.CanExecute = False
        Else
            e.CanExecute = validarDatosParaEjecudion()
        End If

    End Sub



    '--------------------------------------------------------------
    '--------------------------------------------------------------
    ' Botón [Cancelar]
    '--------------------------------------------------------------

    ''' <summary>
    ''' Acción a realizar al pulsar el botón [Cancelar]
    ''' </summary>
    Private Sub StopCommandBinding_Executed(sender As Object, e As ExecutedRoutedEventArgs)
        '------------------------------------------------------------
        ' este es el proceso que se realiza al pulsar el botón [Cancelar]
        Dim objBeep As New Microsoft.VisualBasic.Devices.Audio
        objBeep.PlaySystemSound(System.Media.SystemSounds.Beep)
        '------------------------------------------------------------
        ' Al terminar el proceso de [Cancelar], los botones se colocan en su situación inicial. 
        ActivarElButonCancel(False)

    End Sub


    ''' <summary>
    '''  ¿Se puede ejecutar la acción el botón [Cancelar]?
    '''  True, el botón [Cancelar] se activa, False en caso contrario
    ''' </summary>
    Private Sub StopCommandBinding_CanExecute(sender As Object, e As CanExecuteRoutedEventArgs)
        e.CanExecute = ElBotonCancelarEstaAcivado
    End Sub



    '--------------------------------------------------------------
    '--------------------------------------------------------------
    ' Botón  [Terminar]
    '--------------------------------------------------------------

    ''' <summary>
    ''' Acción a realizar al pulsar el botón [Terminar]
    ''' </summary>
    Private Sub CloseCommandBinding_Executed(sender As Object, e As ExecutedRoutedEventArgs)
        '------------------------------------------------------------
        ' este es el proceso que se realiza al pulsar el botón [Terminar]
        Dim objBeep As New Microsoft.VisualBasic.Devices.Audio
        objBeep.PlaySystemSound(System.Media.SystemSounds.Beep)
        '------------------------------------------------------------
        ' Aquí da igual como estén los botones, porque el proceso se termina
        ' aunque se vuelven a dejar en su situación inicial:
        ' el botón [Cancelar] desactivado y los demás activados
        ActivarElButonCancel(False)
        '------------------------------------------------------------
        'Me.Close()
    End Sub

    Private Sub CloseCommandBinding_CanExecute(sender As Object, e As CanExecuteRoutedEventArgs)
        '------------------------------------------------------------
        ' Nota, 
        ' La activación o no del botón [Terminar], se hace depender del 
        ' estado del botón [Cancelar] para que [Terminar] este 'activado' 
        ' aun en el caso de que los datos sean erróneos es decir, 
        ' (botón [Aceptar], y [Cancelar] desactivados) que es
        ' la situación normal (inicial) de trabajo, 
        ' es, entre otras situaciones cuando la ventana wpf, se abre
        ' y aun no se han introducido datos, de esta forma la ventana puede cerrarse
        '------------------------------------------------------------
        e.CanExecute = Not ElBotonCancelarEstaAcivado
    End Sub

#End Region



#Region "Simulación de un proceso de validación de datos que muestra la ventana"

    Private Property ValidarDatosParaEjecudion() As Boolean = True

    Private Sub RadioButtonDatosCorrectos_Click(sender As Object, e As RoutedEventArgs)
        validarDatosParaEjecudion = True
    End Sub

    Private Sub RadioButtonDatosErroneos_Click(sender As Object, e As RoutedEventArgs)
        validarDatosParaEjecudion = False
    End Sub

#End Region

End Class

↑↑↑

A.2.Enlaces

[Para saber mas]
[Grupo de documentos]
[Documento Index]
[Documento Start]
[Imprimir el Documento]
© 1997 - - La Güeb de Joaquín
Joaquín Medina Serrano
Ésta página es española

Codificación
Fecha de creación
Última actualización
[HTML5 Desarrollado usando CSS3]