在 ListView 中获取鼠标光标下的项目
Getting the item under mouse cursor in ListView
这看起来像是 this or this 问题的重复。但我的问题是如何处理获得的 ListViewItem
?
我已经设置了 ListView
这样的绑定
<ListView ItemsSource="{Binding Data}" ...>
哪里
public ObservableCollection<Item> Data { ... }
如何获得 Item
(来自 ListViewItem
)?
我尝试使用 mvvm 并绑定当前鼠标悬停的项目,类似于 this。但是后来我更跌跌撞撞了:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- this will not work -->
<Setter Property="{Binding MouseoveredItem, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
我的意图清楚吗?我如何获得鼠标控制 Item
?
我不敢相信没有人这样做过。这是代码隐藏尝试(以说明我的问题):
private void ListView_MouseMove(object sender, MouseEventArgs e)
{
var item = VisualTreeHelper.HitTest(listView, Mouse.GetPosition(listView)).VisualHit;
// find ListViewItem (or null)
while (item != null && !(item is ListViewItem))
item = VisualTreeHelper.GetParent(item);
if (item != null)
{
... // item is ListViewItem, how to convert ListViewItem it to Item
}
}
我可以找到 ListViewItem
,但我需要鼠标悬停 Item
的属性,这些属性显示为 SubItems
或隐藏。如何将 ListViewItem
(Item
的视觉视图)转换为 Item
(这是 ListViewItem
所代表的)?
在您的 ViewModel 中使用它:
public ObservableCollection<Item> Data { ... }
public Item SelectedData { get; set; }
在您看来
<ListView ItemsSource="{Binding Data}" SelectedItem="{Binding SelectedData}" ...>
选择会更改,selecteddata 属性也会发生。
当您获得 "ListViewItem" 时,属性 "DataContext" 将 return 您的 "Item"。
在以下代码片段中,ListView
对象与 ObservableCollection<IDataItem>
集合绑定,其中 IDataItem
是自定义接口并继承了 INotifyPropertyChanged
.
在.xaml:
MouseMove="listView_OnMouseMove"
在.xaml.cs:
private void listView_OnMouseMove(object sender, MouseEventArgs e)
{
if (!(e.Source is UIElement selectedObject))
return;
var mousePosition = e.GetPosition(selectedObject);
var dataContextObject = listView.GetObjectAtPoint<ListViewItem>(mousePosition);
if (!(dataContextObject is IDataItem dataItem))
return;
// Deal with the selectedObject under the mouse cursor here
}
// How to get Item under cursor in WPF ListView
// https://www.py4u.net/discuss/1453642 - Answer #2
public static object GetObjectAtPoint<ItemContainer>(this ItemsControl control, Point p)
where ItemContainer : DependencyObject
{
// ItemContainer - can be ListViewItem, or TreeViewItem and so on(depends on control)
var obj = control.GetContainerAtPoint<ItemContainer>(p);
if (obj == null)
return null;
return control.ItemContainerGenerator.ItemFromContainer(obj);
}
private static ItemContainer GetContainerAtPoint<ItemContainer>(this ItemsControl control, Point p)
where ItemContainer : DependencyObject
{
var result = VisualTreeHelper.HitTest(control, p);
var obj = result.VisualHit;
while (VisualTreeHelper.GetParent(obj) != null && !(obj is ItemContainer))
{
obj = VisualTreeHelper.GetParent(obj);
}
// Will return null if not found
return obj as ItemContainer;
}
这看起来像是 this or this 问题的重复。但我的问题是如何处理获得的 ListViewItem
?
我已经设置了 ListView
这样的绑定
<ListView ItemsSource="{Binding Data}" ...>
哪里
public ObservableCollection<Item> Data { ... }
如何获得 Item
(来自 ListViewItem
)?
我尝试使用 mvvm 并绑定当前鼠标悬停的项目,类似于 this。但是后来我更跌跌撞撞了:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- this will not work -->
<Setter Property="{Binding MouseoveredItem, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
我的意图清楚吗?我如何获得鼠标控制 Item
?
我不敢相信没有人这样做过。这是代码隐藏尝试(以说明我的问题):
private void ListView_MouseMove(object sender, MouseEventArgs e)
{
var item = VisualTreeHelper.HitTest(listView, Mouse.GetPosition(listView)).VisualHit;
// find ListViewItem (or null)
while (item != null && !(item is ListViewItem))
item = VisualTreeHelper.GetParent(item);
if (item != null)
{
... // item is ListViewItem, how to convert ListViewItem it to Item
}
}
我可以找到 ListViewItem
,但我需要鼠标悬停 Item
的属性,这些属性显示为 SubItems
或隐藏。如何将 ListViewItem
(Item
的视觉视图)转换为 Item
(这是 ListViewItem
所代表的)?
在您的 ViewModel 中使用它:
public ObservableCollection<Item> Data { ... }
public Item SelectedData { get; set; }
在您看来
<ListView ItemsSource="{Binding Data}" SelectedItem="{Binding SelectedData}" ...>
选择会更改,selecteddata 属性也会发生。
当您获得 "ListViewItem" 时,属性 "DataContext" 将 return 您的 "Item"。
在以下代码片段中,ListView
对象与 ObservableCollection<IDataItem>
集合绑定,其中 IDataItem
是自定义接口并继承了 INotifyPropertyChanged
.
在.xaml:
MouseMove="listView_OnMouseMove"
在.xaml.cs:
private void listView_OnMouseMove(object sender, MouseEventArgs e)
{
if (!(e.Source is UIElement selectedObject))
return;
var mousePosition = e.GetPosition(selectedObject);
var dataContextObject = listView.GetObjectAtPoint<ListViewItem>(mousePosition);
if (!(dataContextObject is IDataItem dataItem))
return;
// Deal with the selectedObject under the mouse cursor here
}
// How to get Item under cursor in WPF ListView
// https://www.py4u.net/discuss/1453642 - Answer #2
public static object GetObjectAtPoint<ItemContainer>(this ItemsControl control, Point p)
where ItemContainer : DependencyObject
{
// ItemContainer - can be ListViewItem, or TreeViewItem and so on(depends on control)
var obj = control.GetContainerAtPoint<ItemContainer>(p);
if (obj == null)
return null;
return control.ItemContainerGenerator.ItemFromContainer(obj);
}
private static ItemContainer GetContainerAtPoint<ItemContainer>(this ItemsControl control, Point p)
where ItemContainer : DependencyObject
{
var result = VisualTreeHelper.HitTest(control, p);
var obj = result.VisualHit;
while (VisualTreeHelper.GetParent(obj) != null && !(obj is ItemContainer))
{
obj = VisualTreeHelper.GetParent(obj);
}
// Will return null if not found
return obj as ItemContainer;
}