When hovering over an item in a list, how can I set a property on another element to the DataContext of the list item?
I’m trying to make an area where I can display a preview of the item currently underneath the mouse cursor. I’m able to do this using code-behind, but I’d like to find an alternative way which could use EventSetters/Binding/Triggers/AttachedProperties or any other means.
The aim is to apply the solution in a more loosely coupled scenario where the ListView control could be in separate resource file and the PreviewControl might be shared by a number of ListViews to show previews of different types.
The following piece of code works, but requires code-behind:
<Window x:Class="Previewer.PreviewWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="PreviewWindow" Height="300" Width="300">
<Window.Resources>
<x:Array x:Key="Data" Type="sys:String">
<sys:String>First</sys:String>
<sys:String>Second</sys:String>
</x:Array>
<CollectionViewSource x:Key="DataSource" Source="{StaticResource Data}"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" x:Name="PreviewControl"/>
<ListView Grid.Row="1" ItemsSource="{Binding Source={StaticResource DataSource}}">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="MouseEnter" Handler="ListViewItem_MouseEnter"/>
<EventSetter Event="MouseLeave" Handler="ListViewItem_MouseLeave"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
The code-behind which at the moment does the trick:
public partial class PreviewWindow : Window
{
public PreviewWindow()
{
InitializeComponent();
}
private void ListViewItem_MouseEnter(object sender, MouseEventArgs e)
{
var listViewItem = (ListViewItem)sender;
PreviewControl.Content= listViewItem.DataContext;
}
private void ListViewItem_MouseLeave(object sender, MouseEventArgs e)
{
var listViewItem = (ListViewItem)sender;
PreviewControl.Content= null;
}
}
Solution 1 (not that generic but simple and works):
encapsulate the logic you already implemented into a custom control, which has a new dependency property (typeof(object)), which represents the HoveredItemContext. In the constructor of your custom list view, you can create the ContainerStyle and attach the events. Set the HoveredItemContext in this EventHandlers and you can bind to this property from the outside:
And here the custom control (works):
Solution 2 (more generic):
I am still working on it on a similar problem but its not yet finished 😉 If i bring it to an end, i will post this here.