tutorial español c# wpf xaml

c# - español - WPF ListView: Adjuntar un evento de doble clic(en un elemento)



xaml tutorial (6)

En su ejemplo, ¿está tratando de captar cuándo se selecciona un elemento en su ListView o cuando se hace clic en un encabezado de columna? Si es el primero, agregaría un controlador SelectionChanged.

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

Si es el último, deberá usar alguna combinación de eventos MouseLeftButtonUp o MouseLeftButtonDown en los elementos de GridViewColumn para detectar un doble clic y tomar las medidas adecuadas. Alternativamente, podría manejar los eventos en el GridView y resolver a partir de allí qué encabezado de columna estaba debajo del mouse.

Tengo el siguiente 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>

¿Cómo puedo adjuntar un evento a cada elemento vinculado que se activará al hacer doble clic en el elemento?


Encontré la solución desde aquí: 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>

DO#:

protected void HandleDoubleClick(object sender, MouseButtonEventArgs e) { var track = ((ListViewItem) sender).Content as Track; //Casting back to the binded Track }


Mi solución se basó en la respuesta de @ epox_sub, que debe buscar para ubicar el controlador de eventos en XAML. El código subyacente no me funcionó porque mis ListViewItems son objetos complejos. La respuesta de @sipwiz fue una gran pista sobre dónde buscar ...

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

La ventaja con esto es que obtienes el enlace DataContext del SelectedItem ( Track en este caso). El elemento seleccionado funciona porque el primer clic del doble clic lo selecciona.


No hay pérdidas de memoria, funciona bien:

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


Para aquellos interesados ​​en mantener el patrón de MVVM en su mayoría, utilicé la respuesta de Andreas Grech para solucionar el problema.

Flujo básico:

El usuario hace doble clic en el elemento -> Manejador de eventos en el código detrás -> ICommand en el modelo de vista

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 se puede encontrar here .

En mi caso, tengo una colección de objetos Project que pueblan ListView . Estos objetos contienen más propiedades que las que se muestran en la lista, y abro ProjectDetailView (una Window WPF) para mostrarlas.

El objeto sender del controlador de eventos es el ListViewItem seleccionado. Posteriormente, el Project que deseo acceder se encuentra dentro de la propiedad de Content .


Basándome en la respuesta de epox_spb , agregué un cheque para evitar errores al hacer doble clic en los encabezados de 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!"); } }