wpf - Cómo enlazar el comando Cerrar a un botón
button wpf-controls (6)
Al principio también estaba teniendo problemas para entender cómo funciona esto, así que quería publicar una mejor explicación de lo que realmente está sucediendo.
De acuerdo con mi investigación, la mejor manera de manejar este tipo de cosas es usando los Enlaces de Comando. Lo que ocurre es que un "Mensaje" se transmite a todo en el programa. Entonces, lo que tienes que hacer es usar CommandBinding
. Lo que esencialmente hace es decir "Cuando escuches este mensaje haz esto".
Entonces en la Pregunta el Usuario está tratando de Cerrar la Ventana. Lo primero que debemos hacer es configurar nuestras funciones que se SystemCommand.CloseWindowCommand
cuando se emita SystemCommand.CloseWindowCommand
. Opcionalmente puede asignar una función que determina si el comando debe ejecutarse. Un ejemplo sería cerrar un formulario y verificar si el usuario ha guardado.
MainWindow.xaml.cs (u otro código subyacente)
void CloseApp( object target, ExecutedRoutedEventArgs e ) {
/*** Code to check for State before Closing ***/
this.Close();
}
void CloseAppCanExecute( object sender, CanExecuteRoutedEventArgs e ) {
/*** Logic to Determine if it is safe to Close the Window ***/
e.CanExecute = true;
}
Ahora tenemos que configurar la "conexión" entre SystemCommands.CloseWindowCommand
y CloseApp
y CloseAppCanExecute
MainWindow.xaml (o cualquier cosa que implemente CommandBindings)
<Window.CommandBindings>
<CommandBinding Command="SystemCommands.CloseWindowCommand"
Executed="CloseApp"
CanExecute="CloseAppCanExecute"/>
</Window.CommandBindings>
Puede omitir CanExecute si sabe que el Comando se debe poder ejecutar siempre. Guardar podría ser un buen ejemplo dependiendo de la Aplicación. Aquí hay un ejemplo:
<Window.CommandBindings>
<CommandBinding Command="SystemCommands.CloseWindowCommand"
Executed="CloseApp"/>
</Window.CommandBindings>
Finalmente, debe indicarle a UIElement que envíe CloseWindowCommand.
<Button Command="SystemCommands.CloseWindowCommand">
En realidad, es algo muy simple de hacer, simplemente configure el enlace entre el Comando y la Función real para Ejecutar, luego diga al Control que envíe el Comando al resto de su programa diciendo "Ok, todos ejecuten sus Funciones para el Comando CloseWindowCommand".
Esta es una muy buena forma de entregar esto porque puedes reutilizar la Función Ejecutada sin tener un contenedor como lo harías con WinForms (usando un evento ClickEvent y llamando a una función dentro de la Función Evento) como:
protected override void OnClick(EventArgs e){
/*** Function to Execute ***/
}
En WPF, adjuntas la función a un comando y le dices al UIElement que ejecute la función adjunta al comando en su lugar.
Espero que esto aclare las cosas...
La forma más fácil es implementar el controlador de eventos ButtonClick
e invocar el método Window.Close()
, pero ¿cómo hacerlo a través de un enlace de Command
?
Creo que en los escenarios del mundo real, un simple manejador de clics es probablemente mejor que los sistemas basados en comandos demasiado complicados, pero puedes hacer algo como eso:
utilizando RelayCommand desde este artículo http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
public class MyCommands
{
public static readonly ICommand CloseCommand =
new RelayCommand( o => ((Window)o).Close() );
}
<Button Content="Close Window"
Command="{X:Static local:MyCommands.CloseCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}"/>
La solución más simple que conozco es establecer la propiedad IsCancel
en true del Button
Cerrar:
<Button Content="Close" IsCancel="True" />
No se necesitan enlaces, ¡WPF lo hará automáticamente!
Referencia: propiedad MSDN Button.IsCancel .
Para .NET 4.5, la clase SystemCommands hará el truco (los usuarios de .NET 4.0 pueden usar WPF Shell Extension Google - Microsoft.Windows.Shell o Nicholas Solution).
<Window.CommandBindings>
<CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}"
CanExecute="CloseWindow_CanExec"
Executed="CloseWindow_Exec" />
</Window.CommandBindings>
<!-- Binding Close Command to the button control -->
<Button ToolTip="Close Window" Content="Close" Command="{x:Static SystemCommands.CloseWindowCommand}"/>
En el código subyacente puede implementar los controladores de esta manera:
private void CloseWindow_CanExec(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void CloseWindow_Exec(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.CloseWindow(this);
}
Todo lo que se necesita es un poco de XAML ...
<Window x:Class="WCSamples.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Close"
Executed="CloseCommandHandler"/>
</Window.CommandBindings>
<StackPanel Name="MainStackPanel">
<Button Command="ApplicationCommands.Close"
Content="Close Window" />
</StackPanel>
</Window>
Y un poco de C # ...
private void CloseCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
this.Close();
}
(adaptado de este artículo de MSDN )
En realidad, es posible sin el código C #. La clave es usar interacciones:
<Button Content="Close">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction TargetObject="{Binding ElementName=window}" MethodName="Close"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Para que esto funcione, simplemente configure x:Name
de su ventana en "ventana", y agregue estos dos espacios de nombres:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
Esto requiere que agregue Expression Blend SDK DLL a su proyecto, específicamente Microsoft.Expression.Interactions
.
En caso de que no tenga Blend, el SDK se puede descargar here .