在ViewModel中检测悬停在ListBoxItem上
本文关键字:ListBoxItem 悬停 检测 ViewModel | 更新日期: 2023-09-27 17:50:19
我有一个自定义项目模板的ListBox
,我想当鼠标悬停在ListBox
中的一个项目上时,在DataContext
上设置一个属性(ListBoxItem
绑定的项目)。
我可以很容易地改变一些视觉上的东西,比如当我用DataTrigger
:
<Style x:Key="MyListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border">
<Image Source="{Binding ImageSource}" Width="32" Height="32" Margin="2,0,2,0"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}"
Value="True">
<Setter TargetName="Border" Property="Background" Value="Red" />
</DataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
但是我不知道如何使DataTrigger
在我的DataContext
上设置属性,所以我的ViewModel可以对悬停做出反应。
不幸的是,在这个项目中,我不能使用通常推荐用于此类任务的Blend交互式DLL,因为我无法在我们的安装过程中引入新的依赖项。
我最终使用附加行为解决了这个问题。这有点麻烦,但确实有效。基本上,您可以将ICommand
放在ViewModel上,其Execute
方法在鼠标进入时被调用,true
作为参数,false
作为鼠标离开时被调用,允许您在视图模型中响应悬停。
public static class MouseOverHelpers
{
public static readonly DependencyProperty MouseOverCommand =
DependencyProperty.RegisterAttached("MouseOverCommand", typeof(ICommand), typeof(MouseOverHelpers),
new PropertyMetadata(null, PropertyChangedCallback));
private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var ui = dependencyObject as UIElement;
if (ui == null) return;
if (args.OldValue != null)
{
ui.RemoveHandler(UIElement.MouseLeaveEvent, new RoutedEventHandler(MouseLeave));
ui.RemoveHandler(UIElement.MouseEnterEvent, new RoutedEventHandler(MouseEnter));
}
if (args.NewValue != null)
{
ui.AddHandler(UIElement.MouseLeaveEvent, new RoutedEventHandler(MouseLeave));
ui.AddHandler(UIElement.MouseEnterEvent, new RoutedEventHandler(MouseEnter));
}
}
private static void ExecuteCommand(object sender, bool parameter)
{
var dp = sender as DependencyObject;
if (dp == null) return;
var command = dp.GetValue(MouseOverCommand) as ICommand;
if (command == null) return;
if (command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
private static void MouseEnter(object sender, RoutedEventArgs e)
{
ExecuteCommand(sender, true);
}
private static void MouseLeave(object sender, RoutedEventArgs e)
{
ExecuteCommand(sender, false);
}
public static void SetMouseOverCommand(DependencyObject o, ICommand value)
{
o.SetValue(MouseOverCommand, value);
}
public static ICommand GetMouseOverCommand(DependencyObject o)
{
return o.GetValue(MouseOverCommand) as ICommand;
}
}
它是这样使用的:
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border"
my:MouseOverHelpers.MouseOverCommand="{Binding MouseOverCommand}">
<Image Source="{Binding ImageSource}" Width="32" Height="32" Margin="2,0,2,0"/>
</Border>
</ControlTemplate>