WPF ListView: Bir çift tıklama (bir öğeye) olayı ekleme


85

Aşağıdakilere sahibim 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>

Öğeye çift tıklandığında ateşlenecek her bağlı öğeye nasıl olay ekleyebilirim?

Yanıtlar:


102

Çözümü buradan buldum: 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
}

14
Stili yeniden kullanmanız gerekmiyorsa, onu doğrudan <ListView.Resources /> bölümüne koyabilir ve x: Anahtarını kaldırabilirsiniz.
David Schmitt

8
Bu benim için de çalıştı. Teşekkürler! BTW, muhtemelen işleyicinizdeki doubleClick olayının köpürmesini durdurmak isteyeceksiniz: e.Handled = true;
Tom A

1
Bununla bir problemim var. Yani, pencerede özel bir denetimde kullanılan ListViews dahil olmak üzere tüm UI öğelerini biçimlendirmek için pencerede x: Anahtarsız stilleri kullanıyorum. Bu olay işleyicisini özel denetimin xaml'sine koymak, pencerede uygulanan stili devre dışı bırakır.
Jeno Csupor

8
Merak ediyorum, bunu yapmanın MVVM'yi ihlal etmeyen başka bir yolu var mı?
Dave

13
Bir uyarı olarak: EventSetterişleyicinin hedefi ListViewItem. Son birkaç günü ciddi bir bellek sızıntısını (bir seferde 20 MB) ayıklamak için harcadım, yalnızca bu dosyaların ListViewItemve ilgili belleğinin bir EventSetter.
Zach Johnson

73

Bellek sızıntısı yok (her öğenin aboneliğini iptal etmeye gerek yok) , iyi çalışıyor:

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

1
Mükemmel, artık bellek sızıntıları hakkında endişelenmenize gerek yok ve açıkçası bu sadece çok daha temiz.
ean5533

3
Listeniz karmaşık bir nesne içeriyorsa bu yeterli değildir. Üst ListViewItem'i bulmak için görsel bir ağaç yardımcısı kullanmanız gerekir ve buradan
veri bağlamını

3
Temiz ve basit. Teşekkürler.
Eternal 21

1
Çok güzel ve yardımsever. Benim durumumda, seçme eylemini gerçekleştiren ek seçim düğmesine sahibim. Bu yüzden çift tıklamayı şu şekilde kullandım: 'MouseDoubleClick = "SelectBtn_Click"' 'private void SelectBtn_Click (nesne gönderen, RoutedEventArgs e) {}'
Kishore

3
Bu yüzden her zaman kabul edilen cevabı geçersiniz. Her ihtimale karşı ...
aggsol

7

Benim çözümüm @ epox_sub'ın XAML'de Olay İşleyiciyi nereye koyacağınıza bakmanız gereken yanıtına dayanıyordu . Arka plan kod benim için işe yaramadı çünkü benim ListViewItemskarmaşık nesnelerim. @ sipwiz'in cevabı nereye bakılacağına dair harika bir ipucuydu ...

void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    var item = ListView.SelectedItem as Track;
    if (item != null)
    {
      MessageBox.Show(item + " Double Click handled!");
    }
}

Bunun bonusu, SelectedItemDataContext bağını alırsınız ( Trackbu durumda). Seçili Öğe, çift tıklamanın ilk tıklaması onu seçtiği için çalışır.


4

MVVM modelini çoğunlukla korumakla ilgilenenler için, bir çözüm bulmak için Andreas Grech'in cevabını kullandım.

Temel akış:

Kullanıcı öğeyi çift tıklar -> Arkasındaki kodda olay işleyici -> Görünüm modelinde 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 burada bulunabilir .

Benim örnekte, ben bir koleksiyona sahip Projectdoldurmak nesneler ListView. Bu nesneler listede gösterilenden daha fazla özellik içeriyor ve bunları görüntülemek için bir ProjectDetailView(WPF Window) açıyorum .

senderOlay gidericiye ait bir amacı seçilir ListViewItem. Daha sonra, Projecterişim istediğim Contentözellik mülk içinde yer alıyor .


3

Örneğinizde, ListView'ınızdaki bir öğe seçildiğinde veya bir sütun başlığına tıklandığında yakalamaya mı çalışıyorsunuz? Eskiyse, bir SelectionChanged işleyici eklersiniz.

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

İkincisi ise, bir çift tıklamayı algılamak ve uygun eylemi gerçekleştirmek için GridViewColumn öğelerinde MouseLeftButtonUp veya MouseLeftButtonDown olaylarının bazı kombinasyonlarını kullanmanız gerekir. Alternatif olarak, GridView üzerindeki olayları işleyebilir ve oradan farenin altında hangi sütun başlığının olduğunu hesaplayabilirsiniz.


Başlıklar değil, sınırlandırılmış öğelerde bir etkinlik istedim
Andreas Grech

Bu benim için yeni. Cevabınızı sunduğunuz için teşekkür ederiz (DoubleClick etkinliği yok ifadesini benimkinden kaldıracağım).
Aaron Clauson

3

Kullandığım alternatif, 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

Bina epox_spb cevabı , ben GridViewColumn başlıklarda hataları çift tıklayarak önlemek için bir çek ekledi.

void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    var dataContext = ((FrameworkElement)e.OriginalSource).DataContext;
    if (dataContext is Track)
    {
        MessageBox.Show("Item's Double Click handled!");
    }
}

çok havalı - PowerShell ile çalışır - - $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; } })Döküm gerekli değildir, ancak ISE'nin tamamlanmasına yardımcı olur
ISE'nin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.