Имею следующее 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>
Как я могу привязать событие к каждому связанному элементу, которое срабатывает при двойном щелчке по элементу?
EventSetter
может привести к утечке памяти, если цель его обработчика живет дольше, чемListViewItem
. Я потратил последние несколько дней на отладку серьезной утечки памяти (20 МБ за раз) только для того, чтобы обнаружить, чтоListViewItem
s и связанная с ними память утекают через файлEventSetter
.Никаких утечек памяти (не нужно отписываться по каждому пункту) , работает нормально:
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!"); } }
источник
Мое решение было основано на ответе @ 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
в данном случае). Выбранный элемент работает, потому что его выбирает первый щелчок двойного щелчка.источник
Для тех, кто в основном заинтересован в поддержке шаблона MVVM, я использовал ответ Андреаса Греча, чтобы обойти его.
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
(WPFWindow
), чтобы отобразить их.sender
Объект обработчика события является выбраннымListViewItem
. Впоследствии то, кProject
чему я хочу получить доступ, содержится вContent
свойстве.источник
В вашем примере вы пытаетесь поймать, когда выбран элемент в вашем ListView или когда нажимается заголовок столбца? Если это первое, вы должны добавить обработчик SelectionChanged.
<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">
В последнем случае вам придется использовать некоторую комбинацию событий MouseLeftButtonUp или MouseLeftButtonDown для элементов GridViewColumn, чтобы обнаружить двойной щелчок и предпринять соответствующие действия. В качестве альтернативы вы можете обрабатывать события в GridView и определять оттуда, какой заголовок столбца был под курсором мыши.
источник
Альтернативой, которую я использовал, является 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>
источник
Основываясь на ответе 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; } })
--- Приведение не требуется, но помогает в ISE получить завершение