J'ai ce qui suit 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>
Comment puis-je attacher un événement à chaque élément lié qui se déclenchera en double-cliquant sur l'élément?
EventSetter
peut entraîner des fuites de mémoire si la cible de son gestionnaire dure plus longtemps que leListViewItem
. J'ai passé les derniers jours à déboguer une grave fuite de mémoire (20 Mo à la fois), pour découvrir queListViewItem
s et leur mémoire associée étaient divulgués via un fichierEventSetter
.Aucune fuite de mémoire (pas besoin de désabonner chaque élément) , fonctionne 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!"); } }
la source
Ma solution était basée sur la réponse de @ epox_sub que vous devriez regarder pour savoir où placer le gestionnaire d'événements dans le XAML. Le code-behind n'a pas fonctionné pour moi car ce
ListViewItems
sont des objets complexes. La réponse de @ sipwiz était un bon indice pour savoir où chercher ...void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var item = ListView.SelectedItem as Track; if (item != null) { MessageBox.Show(item + " Double Click handled!"); } }
Le bonus avec ceci est que vous obtenez la
SelectedItem
liaison DataContext de (Track
dans ce cas). L'élément sélectionné fonctionne car le premier clic du double-clic le sélectionne.la source
Pour ceux qui s'intéressent principalement à la maintenance du modèle MVVM, j'ai utilisé la réponse d'Andreas Grech pour contourner le problème.
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 peut être trouvé ici .
Dans mon cas, j'ai une collection d'
Project
objets qui peuplent leListView
. Ces objets contiennent plus de propriétés que celles affichées dans la liste, et j'ouvre unProjectDetailView
(un WPFWindow
) pour les afficher.L'
sender
objet du gestionnaire d'événements est le selectedListViewItem
. Par la suite, leProject
auquel je veux accéder est contenu dans laContent
propriété.la source
Dans votre exemple, essayez-vous de détecter lorsqu'un élément de votre ListView est sélectionné ou lorsqu'un en-tête de colonne est cliqué? Si c'est le premier, vous ajouteriez un gestionnaire SelectionChanged.
<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">
Si c'est le dernier, vous devrez utiliser une combinaison d'événements MouseLeftButtonUp ou MouseLeftButtonDown sur les éléments GridViewColumn pour détecter un double-clic et prendre les mesures appropriées. Vous pouvez également gérer les événements sur le GridView et déterminer à partir de là quel en-tête de colonne se trouvait sous la souris.
la source
L'alternative que j'ai utilisée est 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>
la source
En me basant sur la réponse d'epox_spb , j'ai ajouté une vérification pour éviter les erreurs lors d'un double-clic dans les en-têtes 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!"); } }
la source
$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; } })
--- La diffusion n'est pas requise mais aide à l'ISE à terminer