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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/728205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 22:46:08  来源:igfitidea点击:

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

c#wpfxaml

提问by Andreas Grech

I have the following ListView:

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

How can I attach an event to every bound item that will fire on double-clicking the item?

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

采纳答案by Andreas Grech

Found the solution from here: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/3d0eaa54-09a9-4c51-8677-8e90577e7bac/

从这里找到解决方案:http: //social.msdn.microsoft.com/Forums/en-US/wpf/thread/3d0eaa54-09a9-4c51-8677-8e90577e7bac/



XAML:

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#:

C#:

protected void HandleDoubleClick(object sender, MouseButtonEventArgs e)
{
    var track = ((ListViewItem) sender).Content as Track; //Casting back to the binded Track
}

回答by sipwiz

In your example are you trying to catch when an item in your ListView is selected or when a column header is clicked on? If it's the former you would add a SelectionChanged handler.

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

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

If it's the latter you would have to use some combination of MouseLeftButtonUp or MouseLeftButtonDown events on the GridViewColumn items to detect a double click and take appropriate action. Alternatively you could handle the events on the GridView and work out from there which column header was under the mouse.

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

回答by epox

No memory leaks, works fine:

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

XAML:

XAML:

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

C#:

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

回答by CAD bloke

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

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

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 (Trackin this case). Selected Item works because the first click of the double-click selects it.

这样做的好处是您可以获得SelectedItem的 DataContext 绑定(Track在这种情况下)。Selected Item 有效,因为双击的第一次单击将它选中。

回答by Kramer

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

基于epox_spb 的回答,我添加了一个检查以避免在双击 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!");
    }
}

回答by Micah Vertal

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

对于那些主要对维护 MVVM 模式感兴趣的人,我使用Andreas Grech 的答案来解决问题。

Basic flow:

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

基本流程:

用户双击项目 -> 隐藏代码中的事件处理程序 -> 视图模型中的 ICommand

ProjectView.xaml:

项目视图.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:

项目视图.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:

项目视图模型.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.

可以在此处找到 DelegateCommand.cs 。

In my instance, I have a collection of Projectobjects 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.

在我的例子中,我有一组Project填充ListView. 这些对象包含的属性比列表中显示的要多,我打开一个ProjectDetailView(一个 WPF Window)来显示它们。

The senderobject of the event handler is the selected ListViewItem. Subsequently, the Projectthat I want access to is contained within the Contentproperty.

sender事件处理程序的对象是 selected ListViewItem。随后,Project我想要访问的 包含在该Content属性中。

回答by Code Name Hyman

Alternative that I used is Event To Command,

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