How to make MouseOver event in MVVM?

2019-03-03 04:22发布

问题:

I use the following code to navigate on button click:

XAML:

<Button x:Name ="Btn_Import" Grid.Row="33" Grid.Column="15" Grid.ColumnSpan="36" Grid.RowSpan="36" Command="{Binding NavigateCommand}"  CommandParameter="ViewImportProgress"/>

ViewModel:

public DelegateCommand<string> NavigateCommand { get; set; }

public MainButtonsViewModel(IRegionManager regionManager, IMainMenuTooltipViewer mainMenuTooltipViewer)
        {
            NavigateCommand = new DelegateCommand<string>(Navigate); 
        }

 private void Navigate(string uri)
        {
            regionManager.RequestNavigate("ScreenNavigationRegion", uri); 


        }

and it works fine. Now my question is what would be equivalent code to make navigation work on MouseOver event instead of MouseClick event, of course in MVVM pattern and using Prism?

回答1:

You can use interractions

declare namespace

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

than you can bind command to event

<Button Content="Navigate" >

    <i:Interaction.Triggers>

        <i:EventTrigger EventName="MouseEnter">

            <i:InvokeCommandAction Command="{Binding NavigateCommand}"   CommandParameter="ViewImportProgress"/>

        </i:EventTrigger>

    </i:Interaction.Triggers>

</Button>


回答2:

I personally prefer to use EventToCommand because of the PassEventArgsToCommand property:

xmlns:cmd ="http://www.galasoft.ch/mvvmlight"

<i:Interaction.Triggers>
    <i:EventTrigger EventName="KeyDown">
        <cmd:EventToCommand Command="{Binding KeyDownCommand}" PassEventArgsToCommand="True" />
    </i:EventTrigger>
</i:Interaction.Triggers>

Which you then use like this:

public ICommand KeyDownCommand { get { return new RelayCommand<KeyEventArgs>(OnKeyDown); } }
private void OnKeyDown(KeyEventArgs args)
{
    if (args.Key == Key.Insert)
        InsertSomething();
}

In practice it's not quite as important with mouse messages because I usually substitute the parameters with a proxy that, in addition to other things, allows my view model to raise capture/release events etc. It is handy though for things like keystrokes or the Closing event etc where you need to get at the args and using a proxy is just adding another unnecessary layer of abstraction.



回答3:

First, you want to set style for your control, say a button, as in the question:

    <Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="{StaticResource SomeBrush}"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Template" Value="{DynamicResource MyButtonTemplate}"/>
</Style>
<ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type ButtonBase}">
    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
        <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="Button.IsDefaulted" Value="True">
            <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
        </Trigger>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" TargetName="border" Value="{Binding IsMouseOverMenuButton, Converter={StaticResource BoolToBrushConverter}}"/>
            <Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Next, set the property in your VM:

public bool IsMouseOverMenuButton
    {
        get => _isMouseOverMenuButton;
        set
        {
            if (_isMouseOverMenuButton != value)
            {
                _isMouseOverMenuButton = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsMouseOverMenuButton"));
            }
        }
    }

And don't forget the converter.

Btw, if you want an easy trick, when on your control on the XAML file, right click it, and in the menu go to, 'Edit Style' . I then go to 'Edit Copy' and it gives me everything I need. You can edit the style directly in your Resource Dictionary.



标签: wpf mvvm Prism