WPF ListView: прикрепление события двойного щелчка (по элементу)
У меня есть следующее 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>
Как я могу прикрепить событие к каждому связанному элементу, который будет срабатывать при двойном щелчке по элементу?
8 ответов
Нашел решение здесь: 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
}
Нет утечек памяти, отлично работает
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.ToString()+" Double Click handled!");
}
}
Бонус с этим вы получаете SelectedItem
привязка DataContext (Track
в этом случае). Выбранный элемент работает, потому что первый щелчок двойным щелчком выделяет его.
Альтернативой, которую я использовал, является 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>
Для тех, кто интересуется в основном поддержкой шаблона MVVM, я использовал ответ Андреаса Греча, чтобы обойти это.
Основной поток:
Пользователь дважды щелкает элемент -> Обработчик события в коде позади -> 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 можно найти здесь.
В моем случае, у меня есть коллекция Project
объекты, которые населяют ListView
, Эти объекты содержат больше свойств, чем показано в списке, и я открываю ProjectDetailView
(WPF Window
) чтобы отобразить их.
sender
объект обработчика события выбран ListViewItem
, Впоследствии Project
к которому я хочу получить доступ, содержится в Content
имущество.
В своем примере вы пытаетесь поймать, когда выбран элемент в вашем ListView или когда щелкается заголовок столбца? Если это первое, вы бы добавили обработчик SelectionChanged.
<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">
Если это последнее, вам придется использовать некоторую комбинацию событий MouseLeftButtonUp или MouseLeftButtonDown для элементов GridViewColumn, чтобы обнаружить двойной щелчок и предпринять соответствующее действие. В качестве альтернативы вы можете обработать события в GridView и определить, какой заголовок столбца находится под мышью.
Основываясь на ответе 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!");
}
}
если вы заполняете свойListview
черезObservableCollection<ItemClass> Items
class ,
и ни один из приведенных выше ответов не работает для вас "как то, что случилось со мной", затем используйте:
private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var item = ((FrameworkElement)e.OriginalSource).DataContext as ItemClass; //<< your class name here
if (item != null)
{
MessageBox.Show(item.UserName + " : item Double Click handled!");
}
}
конечно
ItemClass
будет вашим именем класса setter/getter