WPF ListView: Attaching a double-click (on an item) event
我有以下
1 2 3 4 5 6 7 8 9 10 11 12 13 | <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> |
如何将事件附加到每个双击该项目将触发的绑定项目?
从这里找到解决方案:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/3d0eaa54-09a9-4c51-8677-8e90577e7bac/
XAML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <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#:
1 2 3 4 | protected void HandleDoubleClick(object sender, MouseButtonEventArgs e) { var track = ((ListViewItem) sender).Content as Track; //Casting back to the binded Track } |
没有内存泄漏(无需取消订阅每个项目),工作正常:
XAML:
1 | <ListView ItemsSource="{Binding TrackCollection}" MouseDoubleClick="ListView_MouseDoubleClick" /> |
C#:
1 2 3 4 5 6 7 8 | 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!"); } } |
我的解决方案基于@epox_sub的答案,您应该查看将事件处理程序放在XAML中的位置。后面的代码对我不起作用,因为我的
1 2 3 4 5 6 7 8 | void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var item = ListView.SelectedItem as Track; if (item != null) { MessageBox.Show(item +" Double Click handled!"); } } |
这样做的好处是,您可以获得
对于那些主要对维护MVVM模式感兴趣的人,我使用了Andreas Grech的答案来解决。
Basic flow:
User double-clicks item -> Event handler in code behind -> ICommand in
view model
ProjectView.xaml:
1 2 3 4 5 6 7 8 9 10 | <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:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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可以在这里找到。
在我的实例中,我有一个
事件处理程序的
我使用的替代方法是Event To Command,
1 2 3 4 5 6 7 8 9 | <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> |
在您的示例中,您是否想捕获何时选择了ListView中的一项或单击了列标题?如果是前者,则将添加SelectionChanged处理程序。
1 | <ListView Name="TrackListView" SelectionChanged="MySelectionChanged"> |
如果是后者,则必须在GridViewColumn项目上使用MouseLeftButtonUp或MouseLeftButtonDown事件的某种组合来检测双击并采取适当的措施。或者,您可以处理GridView上的事件,然后从那里计算出鼠标下方的列标题。
在epox_spb的答案的基础上,我添加了一个检查以避免双击GridViewColumn标头中的错误。
1 2 3 4 5 6 7 8 | void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var dataContext = ((FrameworkElement)e.OriginalSource).DataContext; if (dataContext is Track) { MessageBox.Show("Item's Double Click handled!"); } } |