簡體   English   中英

WPF ListView:附加雙擊(在項目上)事件

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

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

如何將事件附加到將在雙擊項目時觸發的每個綁定項目?

從這里找到解決方案: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
}

沒有內存泄漏(無需取消訂閱每個項目) ,工作正常:

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

我的解決方案是基於@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!");
    }
}

這樣做的好處是您獲得了SelectedItem的 DataContext 綁定(在這種情況下為Track )。 所選項目有效,因為第一次單擊雙擊將其選中。

我使用的替代方法是事件到命令,

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

對於那些對主要維護 MVVM 模式感興趣的人,我使用了Andreas Grech 的答案來解決問題。

基本流程:

用戶雙擊項目 -> 代碼中的事件處理程序 -> 視圖模型中的 ICommand

項目視圖.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);
    }
}

項目視圖模型.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。

在我的實例中,我有一個填充ListViewProject對象的集合。 這些對象包含的屬性比列表中顯示的要多,我打開一個ProjectDetailView (一個 WPF Window )來顯示它們。

事件處理程序的sender對象是選定的ListViewItem 隨后,我想要訪問的Project包含在Content屬性中。

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

在您的示例中,您是否試圖捕捉何時選擇 ListView 中的項目或單擊列標題? 如果是前者,您將添加一個 SelectionChanged 處理程序。

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

如果是后者,則必須在 GridViewColumn 項目上使用 MouseLeftButtonUp 或 MouseLeftButtonDown 事件的某種組合來檢測雙擊並采取適當的操作。 或者,您可以處理 GridView 上的事件並從那里計算出鼠標下方的列標題。

如果您Listview通過
ObservableCollection<ItemClass> Items類,
上面的答案都不適合你“發生在我身上”,然后使用:

private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    var item = ((FrameworkElement)e.OriginalSource).DataContext as ItemClass; //<< your class name here

    if (item != null)
    {
        MessageBox.Show(item.UserName + " : item Double Click handled!");
    }
}

當然ItemClass將是您的setter/getter類名稱

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM