次の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>
アイテムをダブルクリックすると起動するすべてのバインドされたアイテムにイベントを添付するにはどうすればよいですか?
ここから解決策を見つけました: 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's answer に基づいていました。XAMLでイベントハンドラーを配置する場所を調べる必要があります。 ListViewItems
は複雑なオブジェクトであるため、コードビハインドは機能しませんでした。 @ sipwiz's answer は、どこを見ればいいかを示すヒントでした.
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
)を取得することです。ダブルクリックの最初のクリックで選択されるため、選択したアイテムが機能します。
主にMVVMパターンの維持に関心がある人のために、 Andreas Grech's answer を使用して回避策を作成しました。
基本フロー:
ユーザーがアイテムをダブルクリック->コードビハインドのイベントハンドラー->ビューモデルの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は here にあります。
私のインスタンスでは、Project
を生成するListView
オブジェクトのコレクションがあります。これらのオブジェクトには、リストに示されているよりも多くのプロパティが含まれており、ProjectDetailView
(WPF Window
)を開いて表示します。
イベントハンドラのsender
オブジェクトは、選択されたListViewItem
です。その後、アクセスしたいProject
がContent
プロパティ内に含まれます。
あなたの例では、リストビューのアイテムが選択されたとき、または列ヘッダーがクリックされたときにキャッチしようとしていますか?前者の場合、SelectionChangedハンドラーを追加します。
<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">
後者の場合、GridViewColumnアイテムでMouseLeftButtonUpイベントまたはMouseLeftButtonDownイベントの組み合わせを使用して、ダブルクリックを検出し、適切なアクションを実行する必要があります。または、GridViewでイベントを処理し、そこからマウスの下にある列ヘッダーを調べることもできます。
epox_spb's answer に基づいて、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!");
}
}