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>

씨#:

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를 제거 할 수 있습니다.
David Schmitt

8
이것은 나에게도 효과적이었습니다. 감사! BTW, 아마도 다음을 설정하여 처리기 내에서 doubleClick 이벤트의 버블 링을 중지하고 싶을 것입니다. e.Handled = true;
Tom A

1
이것에 문제가 있습니다. 즉, 해당 창에서 사용자 지정 컨트롤에 사용 된 ListView를 포함하여 모든 UI 요소의 스타일을 지정하기 위해 창에서 x : Key-less 스타일을 사용합니다. 이 이벤트 처리기를 사용자 지정 컨트롤의 xaml에 넣으면 창에 적용된 스타일이 비활성화됩니다.
Jeno Csupor 2009

8
호기심에서 MVVM을 위반하지 않는 다른 방법이 있습니까?
데이브

13
경고 :를 사용하면 EventSetter핸들러의 타겟이 ListViewItem. 지난 며칠 동안 심각한 메모리 누수 (한 번에 20MB)를 디버깅하는 데 보냈지 만 ListViewItems 및 관련 메모리가 EventSetter.
Zach Johnson

69

메모리 누수 없음 (각 항목 구독을 취소 할 필요 없음 ) , 잘 작동합니다.

XAML :

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

씨#:

    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

3
목록에 복잡한 개체가 포함되어 있으면 충분하지 않습니다. 부모 ListViewItem을 찾으려면 시각적 트리 도우미를 사용해야하며 거기에서 데이터
컨텍스트를 가져올

3
깨끗하고 간단합니다. 감사.
Eternal21

1
매우 친절하고 도움이되었습니다. 제 경우에는 선택 작업을 수행하는 추가 선택 버튼이 있습니다. 그래서 다음과 같이 더블 클릭을 사용했습니다. 'MouseDoubleClick = "SelectBtn_Click"' 'private void SelectBtn_Click (object sender, RoutedEventArgs e) {}'
Kishore

3
이것이 항상 수락 된 답변을지나 스크롤하는 이유입니다. 이런 경우에 ...
aggsol

7

내 솔루션은 @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이 경우). 선택한 항목은 두 번 클릭의 첫 번째 클릭이 선택하기 때문에 작동합니다.


4

주로 MVVM 패턴을 유지하는 데 관심이있는 사람들을 위해 Andreas Grech의 답변 을 사용하여 해결 방법을 만들었습니다.

기본 흐름 :

사용자가 항목-> 코드 숨김의 이벤트 처리기->보기 모델의 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에서 이벤트를 처리하고 마우스 아래에있는 열 머리글을 확인할 수 있습니다.


나는 경계 항목이 아닌 헤더에 이벤트를 원
안드레아스 GRECH

그것은 저에게 새로운 것입니다. 답변을 올려 주셔서 감사합니다 (제에서 DoubleClick 이벤트 없음 문을 삭제하겠습니다).
Aaron Clauson

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>

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

매우 멋진 $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; } })
-PowerShell
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.