web-dev-qa-db-ja.com

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

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

80
Andreas Grech

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

メモリリークはなく、正常に動作します。

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

私の解決策は @ 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)を取得することです。ダブルクリックの最初のクリックで選択されるため、選択したアイテムが機能します。

6
CAD bloke

主にMVVMパターンの維持に関心がある人のために、 Andreas Grech's answer を使用して回避策を作成しました。

基本フロー:

ユーザーがアイテムをダブルクリック->コードビハインドのイベントハンドラー->ビューモデルの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は here にあります。

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

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

3
Micah Vertal

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

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

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

3
sipwiz

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