我有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,这通常被推荐用于这样的任务,因为我无法在安装过程中引入新的依赖项。
答案 0 :(得分:3)
我最终使用附加行为解决了这个问题。这有点麻烦,但确实有效。基本上,您可以在ViewModel上放置ICommand
,其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>