WPF ListView :(アイテムの)ダブルクリックイベントを添付する


85

私は以下を持っています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>

アイテムをダブルクリックすると発生するすべてのバインドされたアイテムにイベントをアタッチするにはどうすればよいですか?

回答:


101

ここから解決策を見つけました: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
}

13
スタイルを再利用する必要がない場合は、スタイルを<ListView.Resources />セクションに直接配置して、x:Keyを削除できます。
デビッドシュミット

8
これは私にとってもうまくいきました。ありがとう!ところで、次のように設定して、ハンドラー内でのdoubleClickイベントのバブリングを停止することをお勧めします。e.Handled= true;
トムA

1
これに問題があります。つまり、ウィンドウでx:Key-lessスタイルを使用して、そのウィンドウのカスタムコントロールで使用されるListViewを含むすべてのUI要素のスタイルを設定します。このイベントハンドラーをカスタムコントロールのxamlに配置すると、ウィンドウに適用されているスタイルが無効になります。
Jeno Csupor 2009

8
好奇心から、MVVMに違反しない別の方法はありますか?
デイブ

13
警告として:EventSetterハンドラーのターゲットがより長く存続する場合、を使用するとメモリリークが発生する可能性がありますListViewItem。私はここ数日、深刻なメモリリーク(一度に20MB)のデバッグに費やしましたが、ListViewItemとそれに関連するメモリがEventSetter。を介してリークされていることがわかりました。
ザックジョンソン

69

メモリリークがなく(各アイテムのサブスクライブを解除する必要はありません、正常に動作します:

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

1
すばらしいです。メモリリークについて心配する必要はもうありません。率直に言って、これは非常にクリーンです。
ean5533 2012年

3
リストに複雑なオブジェクトが含まれている場合、これでは不十分です。親のListViewItemを見つけるには、ビジュアルツリーヘルパーを使用する必要があり、そこから
データコンテキストを取得

3
清潔でシンプル。ありがとう。
Eternal21 2014

1
とても素敵で親切。私の場合、選択アクションを実行する追加の選択ボタンがあります。そこで、次のようにダブルクリックを使用しました。'MouseDoubleClick= "SelectBtn_Click" '' private void SelectBtn_Click(object sender、RoutedEventArgs e){} '
Kishore

3
これが、受け入れられた回答を常に超えてスクロールする理由です。念のため...
aggsol

7

私の解決策は、XAMLのどこにイベントハンドラーを配置するかを調べる必要がある@epox_subの回答に基づいていました。私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この場合)を取得することです。選択したアイテムは、ダブルクリックの最初のクリックで選択されるため機能します。


4

主にMVVMパターンを維持することに関心がある人のために、私はAndreasGrechの回答を使用して回避を作成しました。

基本的な流れ:

ユーザーがアイテムをダブルクリック->コードビハインドのイベントハンドラー->ビューモデルのICommand

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はここにあります

私の例では、私はのコレクションを持っています Projectオブジェクトのます。ListView。これらのオブジェクトには、リストに表示されているよりも多くのプロパティが含まれているため、ProjectDetailView(WPF Window)を開いて表示します。

senderイベントハンドラーのオブジェクトは選択されていListViewItemます。その後、ProjectアクセスしたいものがContentプロパティ内に含まれます。


3

あなたの例では、ListViewのアイテムが選択されたとき、または列ヘッダーがクリックされたときにキャッチしようとしていますか?前者の場合は、SelectionChangedハンドラーを追加します。

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

後者の場合は、GridViewColumnアイテムでMouseLeftButtonUpイベントまたはMouseLeftButtonDownイベントを組み合わせて使用​​し、ダブルクリックを検出して適切なアクションを実行する必要があります。または、GridViewでイベントを処理し、そこからどの列ヘッダーがマウスの下にあるかを調べることもできます。


ヘッダーではなく、境界のあるアイテムに関するイベントが必要でした
Andreas Grech

それは私にとって新しいものです。あなたの答えを提出してくれてありがとう(そして私は私のDoubleDoubleイベントステートメントを削除します)。
アーロンクラウソン

3

私が使用した代替手段は、Event ToCommandです。

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

1

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

非常にクールな- PowerShell-と作品を$myListView.Add_MouseDoubleClick({ Param($sender, $ev); $e = [System.Windows.Input.MouseButtonEventArgs]$ev; $itemData = ([System.Windows.FrameworkElement]$e.OriginalSource).DataContext }); if ($item -ne $null) { Write-Host $itemData; } })---鋳造が完了取得するために必要ですが、ISEのに役立ちますされていません
BananaAcid
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.