【问题标题】:Detect hover over ListBoxItem in ViewModel在 ViewModel 中检测悬停在 ListBoxItem 上
【发布时间】:2014-03-14 11:17:55
【问题描述】:

我有一个带有自定义项目模板的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,因为我无法在我们的安装过程中引入新的依赖项,因此通常推荐用于此类任务。

【问题讨论】:

  • 你需要设置什么类型的属性??
  • 您是否尝试将上下文添加为资源并将DataContext 属性的Value 绑定到DataTrigger 中的该资源?
  • @petchirajan 我只想通知我的视图模型。我刚刚获得了一种相当繁琐的技术,它使用两个附加的行为和两个工作的 ICommand。
  • @HamletHakobyan - 我在这方面尝试的几乎所有东西都遇到了语法错误。
  • 不幸或幸运的是,如果不包括Interaction.Triggers,这种繁琐的技术(附加行为)可能是MVVM风格中唯一可能的选择。

标签: c# wpf xaml data-binding mvvm


【解决方案1】:

我最终使用附加行为解决了这个问题。这有点麻烦,但它确实有效。基本上,您可以在 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>

【讨论】:

  • 不知道别人怎么样,但我喜欢这个解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-31
相关资源
最近更新 更多