WPF ListView: Attaching a double-click (on an item) event

前端 未结 7 1357
陌清茗
陌清茗 2020-11-29 19:12

I have the following ListView:


    
        
            

        
相关标签:
7条回答
  • 2020-11-29 19:49

    My solution was based on @epox_sub's answer which you should look at for where to put the Event Handler in the XAML. The code-behind didn't work for me because my ListViewItems are complex objects. @sipwiz's answer was a great hint for where to look...

    void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        var item = ListView.SelectedItem as Track;
        if (item != null)
        {
          MessageBox.Show(item + " Double Click handled!");
        }
    }
    

    The bonus with this is you get the SelectedItem's DataContext binding (Track in this case). Selected Item works because the first click of the double-click selects it.

    0 讨论(0)
  • 2020-11-29 19:51

    Building on epox_spb's answer, I added in a check to avoid errors when double clicking in the GridViewColumn headers.

    void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        var dataContext = ((FrameworkElement)e.OriginalSource).DataContext;
        if (dataContext is Track)
        {
            MessageBox.Show("Item's Double Click handled!");
        }
    }
    
    0 讨论(0)
  • 2020-11-29 19:54

    Found the solution from here: 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
    }
    
    0 讨论(0)
  • 2020-11-29 19:55

    Alternative that I used is 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>
    
    0 讨论(0)
  • 2020-11-29 19:59

    For those interested in mostly maintaining the MVVM pattern, I used Andreas Grech's answer to make a work-around.

    Basic flow:

    User double-clicks item -> Event handler in code behind -> ICommand in view model

    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 can be found here.

    In my instance, I have a collection of Project objects that populate the ListView. These objects contain more properties than are shown in the list, and I open a ProjectDetailView (a WPF Window) to display them.

    The sender object of the event handler is the selected ListViewItem. Subsequently, the Project that I want access to is contained within the Content property.

    0 讨论(0)
  • 2020-11-29 20:08

    No memory leaks (no need to unsubscribe each item), works fine:

    XAML:

    <ListView MouseDoubleClick="ListView_MouseDoubleClick" ItemsSource="{Binding TrackCollection}" />
    

    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!");
            }
        }
    
    0 讨论(0)
提交回复
热议问题