J'ai la ListView
suivante:
<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 sera déclenché en double-cliquant sur celui-ci?
Trouvez la solution à partir d'ici: http://social.msdn.Microsoft.com/Forums/en-US/wpf/thread/3d0eaa54-09a9-4c51-8677-8e90577e7bac/
XAML:
<UserControl.Resources>
<Style x:Key="itemstyle" TargetType="{x:Type ListViewItem}">
<EventSetter Event="MouseDoubleClick" Handler="HandleDoubleClick" />
</Style>
</UserControl.Resources>
<ListView Name="TrackListView" ItemContainerStyle="{StaticResource itemstyle}">
<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 #:
protected void HandleDoubleClick(object sender, MouseButtonEventArgs e)
{
var track = ((ListViewItem) sender).Content as Track; //Casting back to the binded Track
}
Aucune fuite de mémoire, 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!");
}
}
Ma solution était basée sur la réponse de @ epox_sub que vous devriez rechercher pour savoir où placer le gestionnaire d'événements dans le XAML. Le code-behind n'a pas fonctionné pour moi car mes ListViewItems
sont des objets complexes. La réponse de @ sipwiz était un bon indice pour savoir où regarder ...
void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var item = ListView.SelectedItem as Track;
if (item != null)
{
MessageBox.Show(item.ToString()+" Double Click handled!");
}
}
Le bonus à cela est que vous obtenez la liaison DataContext de SelectedItem
(Track
dans ce cas). L'élément sélectionné fonctionne parce que le premier clic du double-clic le sélectionne.
Pour ceux qui souhaitaient principalement conserver le modèle MVVM, j'ai utilisé la réponse d'Andreas Grech pour créer une solution de contournement.
Flux de base:
L'utilisateur double-clique sur l'élément -> Gestionnaire d'événements dans le code derrière -> ICommand dans voir le modèle
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'objets Project
qui remplissent la ListView
. Ces objets contiennent plus de propriétés que ne le montre la liste et j'ouvre une ProjectDetailView
(une WPF Window
) pour les afficher.
L'objet sender
du gestionnaire d'événements est la ListViewItem
sélectionnée. Par la suite, la Project
à laquelle je veux accéder est contenue dans la propriété Content
.
Dans votre exemple, essayez-vous de capturer 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 cas, 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. Sinon, vous pouvez 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.
En me basant sur la réponse de epox_spb , j’ai ajouté à une vérification pour éviter les erreurs lors du 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!");
}
}