Mam 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>
Jak mogę dołączyć zdarzenie do każdego związanego przedmiotu, które zostanie uruchomione po dwukrotnym kliknięciu przedmiotu?
EventSetter
może prowadzić do wycieków pamięci, jeśli cel jego obsługi żyje dłużej niżListViewItem
. Spędziłem kilka ostatnich dni na debugowaniu poważnego wycieku pamięci (20 MB na raz), tylko po to, aby dowiedzieć się, żeListViewItem
s i związana z nimi pamięć wyciekły przez plikEventSetter
.Brak wycieków pamięci (nie ma potrzeby anulowania subskrypcji każdego elementu) , działa dobrze:
XAML:
<ListView ItemsSource="{Binding TrackCollection}" MouseDoubleClick="ListView_MouseDoubleClick" />
DO#:
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!"); } }
źródło
Moje rozwiązanie opierało się na odpowiedzi @ epox_sub, na którą powinieneś zwrócić uwagę, gdzie umieścić Event Handler w XAML. Kod nie działał dla mnie, ponieważ moje
ListViewItems
są złożone obiekty. Odpowiedź @ sipwiz była świetną wskazówką, gdzie szukać ...void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var item = ListView.SelectedItem as Track; if (item != null) { MessageBox.Show(item + " Double Click handled!"); } }
Dodatkową korzyścią jest to, że otrzymujesz
SelectedItem
powiązanie DataContext (Track
w tym przypadku). Wybrany element działa, ponieważ pierwsze kliknięcie dwukrotnego kliknięcia powoduje jego zaznaczenie.źródło
Dla tych, którzy są zainteresowani głównie utrzymaniem wzorca MVVM, użyłem odpowiedzi Andreasa Grecha, aby dokonać obejścia.
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 można znaleźć tutaj .
W moim przypadku mam kolekcję
Project
obiektów, które wypełniająListView
. Te obiekty zawierają więcej właściwości niż są pokazane na liście, a ja otwieram plikProjectDetailView
(WPFWindow
), aby je wyświetlić.sender
Celem obsługi zdarzenia jest wybranyListViewItem
. Następnie element, doProject
którego chcę uzyskać dostęp, jest zawarty wContent
nieruchomości.źródło
Czy w Twoim przykładzie próbujesz złapać, gdy element w Twoim ListView jest zaznaczony lub gdy kliknięto nagłówek kolumny? Jeśli jest to pierwszy, należy dodać procedurę obsługi SelectionChanged.
<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">
Jeśli to drugie, musisz użyć kombinacji zdarzeń MouseLeftButtonUp lub MouseLeftButtonDown na elementach GridViewColumn, aby wykryć dwukrotne kliknięcie i podjąć odpowiednią akcję. Alternatywnie możesz obsłużyć zdarzenia w widoku GridView i ustalić, który nagłówek kolumny znajdował się pod myszą.
źródło
Alternatywą, której użyłem, jest 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>
źródło
Opierając się na odpowiedzi epox_spb , dodałem czek, aby uniknąć błędów po dwukrotnym kliknięciu nagłówków 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!"); } }
źródło
$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; } })
---