Cómo traducir los eventos de CodeBehind WPF; ¿Evento, manejador, eventos de patrón MVVM?
Pregunta
Estoy tratando de traducir eventos WPF CodeBehid como Event, Handler, Eventsetter al patrón MVVM. No se me permite usar System.Windows.Controls ya que estoy usando MVVM. Y también estoy evitando la biblioteca de terceros para resolver este problema.
¿Alguien puede explicar cómo convertir el siguiente manejador de eventos CodeBehind a MVVM Event-Handler? Explique todo lo que pueda mientras escribe respuesta.
Código XAML
<DataGridCheckBoxColumn Header="Select" Binding="{Binding Path=IsSelected}">
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="DataGridCell">
<EventSetter Event="MouseLeftButtonUp" Handler="ApprovedMouseUp"></EventSetter>
</Style>
</DataGridCheckBoxColumn.CellStyle>
</DataGridCheckBoxColumn>
Código detrás
private void ApprovedMouseUp(object sender, MouseButtonEventArgs e)
{
if(sender is DataGridCell)
{
var temp = (sender as DataGridCell).Content;
if(temp is CheckBox) (temp as CheckBox).IsChecked = !(temp as CheckBox).IsChecked;
}
}
Solución
Hay pocas reglas de pulgar con respecto a MVVM ...
- Su
Models
yViewModles
no debe referirseSystem.Windows.Controls
espacio de nombres. - Su
Models
yViewModles
no debe manejar eventos. UsarICommand
interfaz para eso. RoutedCommand
no es válido en modelos / ViewModels (debido al punto 2). De ahí el uso DelegateCommand /RelayCommand
Dicho esto, todos los puntos anteriores son perfectamente permitió Si has escrito un Comportamiento adjunto en MVVM.
Otros consejos
Usted tiene un par de opciones:
Adjunte el controlador de eventos en XAML, pero lo único que hace el controlador de eventos es llamar al modelo de vista que pasa en los argumentos apropiados (es importante no pasar ningún elemento de nivel de GUI al modelo de vista, solo los datos necesarios para realizar la acción)
Utilizar el EventToCommand Comportamiento (exhibido aquí) para adjuntar una instancia de un iCommand (desde su modelo de vista) a un evento en su vista
Siempre que no esté tratando de establecer estos controladores de eventos en estilos o plantillas, recomendaría buscar la opción #1: no existe una ley de hierro que le prohíba usar controladores de eventos cuando sea conveniente, siempre que el modelo de vista sea lo que realmente realiza todo el trabajo
Editar: Opción #1
private void ApprovedMouseUp(object sender, MouseButtonEventArgs e)
{
if(sender is DataGridCell)
{
var checkBox= (sender as DataGridCell).Content as CheckBox;
if(checkBox != null)
{
var viewModel = (MyViewModel)checkBox.DataContext;
viewModel.ToggleApprovedStatus();
}
}
}
También puedes usar Caliburn Micro Bibliotecas para poder adjuntar un controlador en ViewModel a un evento a la vista.
Código de muestra:
... xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"....
<Button Content="Edit" DataContext="{Binding Path=VmInstance}"
cal:Message.Attach="[Event Click] = [Action EditFilter]" />