Eu tenho o seguinte 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>
Como posso anexar um evento a cada item vinculado que será disparado ao clicar duas vezes no item?
EventSetter
pode causar vazamentos de memória se o destino de seu manipulador viver mais do que oListViewItem
. Passei os últimos dias depurando um sério vazamento de memória (20 MB por vez), apenas para descobrir que seListViewItem
a memória associada estava vazando por meio de umEventSetter
.Sem vazamentos de memória (não há necessidade de cancelar a assinatura de cada item) , funciona bem:
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!"); } }
fonte
Minha solução foi baseada na resposta de @epox_sub, que você deve examinar para saber onde colocar o Event Handler no XAML. O code-behind não funcionou para mim porque
ListViewItems
são objetos complexos. A resposta de @sipwiz foi uma ótima dica de onde procurar ...void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var item = ListView.SelectedItem as Track; if (item != null) { MessageBox.Show(item + " Double Click handled!"); } }
O bônus com isso é que você obtém a
SelectedItem
vinculação DataContext do (Track
neste caso). Item selecionado funciona porque o primeiro clique do clique duplo o seleciona.fonte
Para aqueles interessados principalmente em manter o padrão MVVM, usei a resposta de Andreas Grech para fazer uma solução alternativa .
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 pode ser encontrado aqui .
No meu caso, tenho uma coleção de
Project
objetos que povoam oListView
. Esses objetos contêm mais propriedades do que as mostradas na lista e abro umProjectDetailView
(um WPFWindow
) para exibi-los.O
sender
objeto do manipulador de eventos é o selecionadoListViewItem
. Posteriormente, oProject
que desejo acessar está contido naContent
propriedade.fonte
Em seu exemplo, você está tentando capturar quando um item em seu ListView é selecionado ou quando um cabeçalho de coluna é clicado? Se for o primeiro, você adicionaria um manipulador SelectionChanged.
<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">
Se for o último, você terá que usar alguma combinação de eventos MouseLeftButtonUp ou MouseLeftButtonDown nos itens GridViewColumn para detectar um clique duplo e executar a ação apropriada. Alternativamente, você pode manipular os eventos no GridView e descobrir a partir daí qual cabeçalho da coluna está sob o mouse.
fonte
A alternativa que usei é 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>
fonte
Com base na resposta de epox_spb , adicionei uma verificação para evitar erros ao clicar duas vezes nos cabeçalhos 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!"); } }
fonte
$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; } })
--- A fundição não é necessária, mas ajuda no ISE a obter a conclusão