En una aplicación WPF que usa MVVM, tengo un control de usuario con un elemento de vista de lista. En tiempo de ejecución, utilizará el enlace de datos para llenar la vista de lista con una colección de objetos.
¿Cuál es la forma correcta de adjuntar un evento de doble clic a los elementos de la vista de lista para que cuando se haga doble clic en un elemento de la vista de lista, se active un evento correspondiente en el modelo de vista y tenga una referencia al elemento en el que se hizo clic?
¿Cómo se puede hacer de una manera MVVM limpia, es decir, sin código detrás en la Vista?
Puedo hacer que esto funcione con .NET 4.5. Parece sencillo y no se necesita ningún tercero o código detrás.
fuente
InputBindings
están disponibles en .NET 3.0 y no están disponibles en Silverlight.Me gusta usar Comandos y Comportamientos de comandos adjuntos . Marlon Grech tiene una muy buena implementación de los Comportamientos de comandos adjuntos. Usando estos, podríamos asignar un estilo a la propiedad ItemContainerStyle de ListView que establecerá el comando para cada ListViewItem.
Aquí configuramos el comando para que se active en el evento MouseDoubleClick, y CommandParameter, será el objeto de datos en el que hacemos clic. Aquí estoy viajando por el árbol visual para obtener el comando que estoy usando, pero también podría crear comandos para toda la aplicación con la misma facilidad.
Para los comandos, puede implementar un ICommand directamente o usar algunos de los ayudantes como los que vienen en MVVM Toolkit .
fuente
acb:
= AttachedCommandBehavior. El código se puede encontrar en el primer enlace de la respuestaHe encontrado una forma muy fácil y limpia de hacer esto con los activadores de eventos de Blend SDK. MVVM limpio, reutilizable y sin código subyacente.
Probablemente ya tengas algo como esto:
Ahora incluya un ControlTemplate para ListViewItem como este si aún no usa uno:
GridViewRowPresenter será la raíz visual de todos los elementos "dentro" que componen un elemento de fila de lista. Ahora podríamos insertar un disparador allí para buscar eventos enrutados MouseDoubleClick y llamar a un comando a través de InvokeCommandAction como este:
Si tiene elementos visuales "encima" del GridRowPresenter (probablemente comenzando con una cuadrícula), también puede colocar el Trigger allí.
Desafortunadamente, los eventos MouseDoubleClick no se generan a partir de todos los elementos visuales (son de Controls, pero no de FrameworkElements, por ejemplo). Una solución alternativa es derivar una clase de EventTrigger y buscar MouseButtonEventArgs con un ClickCount de 2. Esto filtra eficazmente todos los eventos que no son MouseButtonEvents y todos los MoseButtonEvents con un ClickCount! = 2.
Ahora podemos escribir esto ('h' es el espacio de nombres de la clase auxiliar anterior):
fuente
Me doy cuenta de que esta discusión tiene un año, pero con .NET 4, ¿hay alguna idea sobre esta solución? Estoy absolutamente de acuerdo en que el objetivo de MVVM NO es eliminar un código detrás de un archivo. También creo firmemente que el hecho de que algo sea complicado no significa que sea mejor. Esto es lo que puse en el código detrás:
fuente
Puede utilizar la función Acción de Caliburn para asignar eventos a métodos en su ViewModel. Suponiendo que tiene un
ItemActivated
método en suViewModel
, el XAML correspondiente se vería así:Para obtener más detalles, puede examinar la documentación y las muestras de Caliburn.
fuente
Me resulta más sencillo vincular el comando cuando se crea la vista:
En mi caso se
BindAndShow
ve así (updatecontrols + avalondock):Aunque el enfoque debería funcionar con cualquier método que tenga para abrir nuevas vistas.
fuente
Vi la solución de Rushui con InuptBindings, pero todavía no pude acceder al área de ListViewItem donde no había texto, incluso después de configurar el fondo en transparente, así que lo resolví usando diferentes plantillas.
Esta plantilla es para cuando se ha seleccionado ListViewItem y está activo:
Esta plantilla es para cuando se ha seleccionado ListViewItem y está inactivo:
Este es el estilo predeterminado utilizado para ListViewItem:
Lo que no me gusta es la repetición del TextBlock y su enlace de texto, no sé si puedo evitar declarar eso en una sola ubicación.
¡Espero que esto ayude a alguien!
fuente
listviewitem
, probablemente no le importe si ya está seleccionado o no. También es importante tener en cuenta que es posible que el efecto de resaltado también deba modificarse para que coincida con ellistview
estilo. Votado a favor.Logré hacer esta funcionalidad con el marco .Net 4.7 utilizando la biblioteca de interactividad, en primer lugar, asegúrese de declarar el espacio de nombres en el archivo XAML
Luego, configure el Activador de eventos con su respectiva InvokeCommandAction dentro de ListView como se muestra a continuación.
Ver:
Adaptar el código anterior debería ser suficiente para que el evento de doble clic funcione en su ViewModel, sin embargo, le agregué la clase Model y View Model de mi ejemplo para que pueda tener la idea completa.
Modelo:
Ver modelo:
En caso de que necesite la implementación de la clase DelegateCommand .
fuente
Aquí hay un comportamiento que hace eso en ambos
ListBox
yListView
.Aquí está la clase de extensión utilizada para encontrar el padre.
Uso:
fuente