Tengo lo siguiente ListView
:
<ListView Name="TrackListView">
<ListView.View>
<GridView>
<GridViewColumn Header="Title" Width="100"
HeaderTemplate="{StaticResource BlueHeader}"
DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Artist" Width="100"
HeaderTemplate="{StaticResource BlueHeader}"
DisplayMemberBinding="{Binding Album.Artist.Name}" />
</GridView>
</ListView.View>
</ListView>
¿Cómo puedo adjuntar un evento a cada elemento vinculado que se activará al hacer doble clic en el elemento?
EventSetter
puede provocar pérdidas de memoria si el objetivo de su controlador vive más tiempo que elListViewItem
. Pasé los últimos días depurando una fuga de memoria grave (20 MB a la vez), solo para descubrir queListViewItem
se estaban filtrando s y su memoria asociada a través de un archivoEventSetter
.Sin fugas de memoria (no es necesario cancelar la suscripción de cada elemento) , funciona bien:
XAML:
<ListView ItemsSource="{Binding TrackCollection}" MouseDoubleClick="ListView_MouseDoubleClick" />
C#:
void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var item = ((FrameworkElement) e.OriginalSource).DataContext as Track; if (item != null) { MessageBox.Show("Item's Double Click handled!"); } }
fuente
Mi solución se basó en la respuesta de @ epox_sub, que debe buscar dónde colocar el controlador de eventos en el XAML. El código subyacente no funcionó para mí porque
ListViewItems
son objetos complejos. La respuesta de @ sipwiz fue una gran pista sobre dónde buscar ...void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var item = ListView.SelectedItem as Track; if (item != null) { MessageBox.Show(item + " Double Click handled!"); } }
La ventaja de esto es que obtiene el
SelectedItem
enlace DataContext (Track
en este caso). El elemento seleccionado funciona porque el primer clic del doble clic lo selecciona.fuente
Para aquellos interesados en mantener principalmente el patrón MVVM, utilicé la respuesta de Andreas Grech para hacer una solución .
ProjectView.xaml:
<UserControl.Resources> <Style TargetType="ListViewItem" x:Key="listViewDoubleClick"> <EventSetter Event="MouseDoubleClick" Handler="ListViewItem_MouseDoubleClick"/> </Style> </UserControl.Resources> ... <ListView ItemsSource="{Binding Projects}" ItemContainerStyle="{StaticResource listViewDoubleClick}"/>
ProjectView.xaml.cs:
public partial class ProjectView : UserControl { public ProjectView() { InitializeComponent(); } private void ListViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e) { ((ProjectViewModel)DataContext) .ProjectClick.Execute(((ListViewItem)sender).Content); } }
ProjectViewModel.cs:
public class ProjectViewModel { public ObservableCollection<Project> Projects { get; set; } = new ObservableCollection<Project>(); public ProjectViewModel() { //Add items to Projects } public ICommand ProjectClick { get { return new DelegateCommand(new Action<object>(OpenProjectInfo)); } } private void OpenProjectInfo(object _project) { ProjectDetailView project = new ProjectDetailView((Project)_project); project.ShowDialog(); } }
DelegateCommand.cs se puede encontrar aquí .
En mi caso, tengo una colección de
Project
objetos que pueblan elListView
. Estos objetos contienen más propiedades de las que se muestran en la lista y abro unProjectDetailView
(un WPFWindow
) para mostrarlas.El
sender
objeto del controlador de eventos es el seleccionadoListViewItem
. Posteriormente, el objeto alProject
que quiero acceder está contenido dentro de laContent
propiedad.fuente
En su ejemplo, ¿está tratando de detectar cuándo se selecciona un elemento en su ListView o cuando se hace clic en el encabezado de una columna? Si es lo primero, agregaría un controlador SelectionChanged.
<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">
Si es el último, tendría que usar alguna combinación de eventos MouseLeftButtonUp o MouseLeftButtonDown en los elementos GridViewColumn para detectar un doble clic y tomar la acción apropiada. Alternativamente, puede manejar los eventos en GridView y determinar desde allí qué encabezado de columna estaba debajo del mouse.
fuente
La alternativa que utilicé es Event To Command,
<ListView ItemsSource="{Binding SelectedTrack}" SelectedItem="{Binding SelectedTrack}" > <i:Interaction.Triggers> <i:EventTrigger EventName="MouseDoubleClick"> <i:InvokeCommandAction Command="{Binding SelectTrackCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> ........... ........... </ListView>
fuente
Sobre la base de la respuesta de epox_spb , agregué una verificación para evitar errores al hacer doble clic en los encabezados GridViewColumn.
void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var dataContext = ((FrameworkElement)e.OriginalSource).DataContext; if (dataContext is Track) { MessageBox.Show("Item's Double Click handled!"); } }
fuente
$myListView.Add_MouseDoubleClick({ Param($sender, $ev); $e = [System.Windows.Input.MouseButtonEventArgs]$ev; $itemData = ([System.Windows.FrameworkElement]$e.OriginalSource).DataContext }); if ($item -ne $null) { Write-Host $itemData; } })
--- No se requiere