WPF ListView:附加双击(在项目上)事件

时间:2009-04-08 01:40:55

标签: c# wpf xaml

我有以下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>

如何将事件附加到双击项目时将触发的每个绑定项目?

7 个答案:

答案 0 :(得分:95)

从此处找到解决方案: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
}

答案 1 :(得分:62)

没有内存泄漏,工作正常:

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!");
        }
    }

答案 2 :(得分:5)

我的解决方案基于@epox_sub's answer,您应该查看将事件处理程序放在XAML中的位置。代码隐藏对我不起作用,因为我的ListViewItems是复杂的对象。 @sipwiz's answer是一个很好的暗示在哪里看......

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

这样做可以获得SelectedItem的DataContext绑定(在这种情况下为Track)。所选项目有效,因为双击的第一次单击会选择它。

答案 3 :(得分:3)

在您的示例中,您是否尝试捕获ListView中的项目被选中或单击列标题时?如果是前者,你会添加一个SelectionChanged处理程序。

<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">

如果是后者,则必须在GridViewColumn项目上使用MouseLeftButtonUp或MouseLeftButtonDown事件的某种组合来检测双击并采取适当的操作。或者,您可以处理GridView上的事件,并从那里找出哪个列标题位于鼠标下。

答案 4 :(得分:3)

对于那些对维护MVVM模式感兴趣的人,我使用Andreas Grech's answer来解决这个问题。

  

基本流程:

     

用户双击项目 - &gt;代码背后的事件处理程序 - &gt; ICommand in   查看模型

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 here

在我的实例中,我有一组填充Project的{​​{1}}个对象。这些对象包含的属性多于列表中显示的属性,我打开ListView(WPF ProjectDetailView)来显示它们。

事件处理程序的Window对象是选定的sender。随后,我要访问的ListViewItem包含在Project属性中。

答案 5 :(得分:3)

我使用的替代方法是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>

答案 6 :(得分:1)

epox_spb's answer的基础上,我添加了一个检查,以避免在双击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!");
    }
}