WPF MouseLeave没有通过命令

时间:2017-03-15 03:13:23

标签: wpf xaml

我启动了MVVM项目,并在ViewModel上设置了TextBlock上的View绑定所有事件。我设置了3个命令(MouseEnter,MouseLeave和MouseDown)。但只有MouseEnter和MouseDown被触发,MouseLeave事件没有触发

这是视图

<Window x:Class="SilentUpdate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:local="clr-namespace:SilentUpdate"
        xmlns:res="clr-namespace:System;assembly=mscorlib"        
        mc:Ignorable="d"
        Background="Gainsboro"
        WindowStartupLocation="CenterScreen" WindowStyle="None"
        Title="" Height="600" Width="1024">
    <Grid>
        <Grid.Resources>
            <ResourceDictionary>
                <Style TargetType="TextBlock" x:Key="IconText">
                    <Setter Property="FontSize" Value="32"/>
                    <Setter Property="Foreground" Value="#ADADAD"/>
                    <Setter Property="FontFamily" Value="pack://application:,,,/Resources/#Segoe UI Symbol"/>
                    <Setter Property="Margin" Value="10,10,10,10"/>
                </Style>
                <res:String x:Key="homeIcon">&#xE10F;</res:String>
                <res:String x:Key="settingsIcon">&#xE115;</res:String>
                <res:String x:Key="previewIcon">&#xE12A;</res:String>
                <res:String x:Key="runIcon">&#xE102;</res:String>
                <res:String x:Key="saveIcon">&#xE105;</res:String>
                <res:String x:Key="exitIcon">&#xE10A;</res:String>
                <res:String x:Key="warningIcon">&#xE113;</res:String>
                <res:String x:Key="folderIcon">&#xE188;</res:String>
            </ResourceDictionary>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <StackPanel x:Name="Navibar" Orientation="Vertical" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Background="#0096C1">
            <TextBlock Name="home" 
                       Foreground="{Binding HomeColor}"
                       Text="{StaticResource homeIcon}"                        
                       Style="{StaticResource IconText}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseEnter">
                        <i:InvokeCommandAction Command="{Binding EventMouseOver}" 
                                               CommandParameter="{Binding ElementName=home}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <i:InvokeCommandAction Command="{Binding MouseLeaveButton}" 
                                               CommandParameter="{Binding ElementName=home}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseDown">
                        <i:InvokeCommandAction Command="{Binding HomeCommand}"
                                               CommandParameter="{Binding ElementName=home}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBlock>
            <TextBlock Name="settings"                        
                       Text="{StaticResource settingsIcon}"                        
                       Style="{StaticResource IconText}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseEnter">
                        <i:InvokeCommandAction Command="{Binding EventMouseOver}" 
                                               CommandParameter="{Binding ElementName=settings}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <i:InvokeCommandAction Command="{Binding MouseLeaveButton}" 
                                               CommandParameter="{Binding ElementName=settings}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseDown">
                        <i:InvokeCommandAction Command="{Binding SettingCommand}"
                                               CommandParameter="{Binding ElementName=settings}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBlock>
            <TextBlock Name="preview" 
                       IsEnabled="{Binding PreviewStatus, Mode=OneWay}"
                       Text="{StaticResource previewIcon}"                        
                       Style="{StaticResource IconText}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseEnter">
                        <i:InvokeCommandAction Command="{Binding EventMouseOver}" 
                                               CommandParameter="{Binding ElementName=preview}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <i:InvokeCommandAction Command="{Binding MouseLeaveButton}" 
                                               CommandParameter="{Binding ElementName=preview}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseDown">
                        <i:InvokeCommandAction Command="{Binding PreviewCommand}"
                                               CommandParameter="{Binding ElementName=preview}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBlock>
            <TextBlock Name="run" 
                       IsEnabled="{Binding RunStatus, Mode=OneWay}"
                       Text="{StaticResource runIcon}"                        
                       Style="{StaticResource IconText}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseEnter">
                        <i:InvokeCommandAction Command="{Binding EventMouseOver}" 
                                               CommandParameter="{Binding ElementName=run}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <i:InvokeCommandAction Command="{Binding MouseLeaveButton}" 
                                               CommandParameter="{Binding ElementName=run}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseDown">
                        <i:InvokeCommandAction Command="{Binding RunCommand}"
                                               CommandParameter="{Binding ElementName=run}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBlock>
            <TextBlock Name="save" 
                       IsEnabled="{Binding SaveStatus, Mode=OneWay}"
                       Text="{StaticResource saveIcon}"                        
                       Style="{StaticResource IconText}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseEnter">
                        <i:InvokeCommandAction Command="{Binding EventMouseOver}" 
                                               CommandParameter="{Binding ElementName=save}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <i:InvokeCommandAction Command="{Binding MouseLeaveButton}" 
                                               CommandParameter="{Binding ElementName=save}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseDown">
                        <i:InvokeCommandAction Command="{Binding SaveCommand}"
                                               CommandParameter="{Binding ElementName=save}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBlock>
            <TextBlock Name="exit" 
                       Text="{StaticResource exitIcon}"                        
                       Style="{StaticResource IconText}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseEnter">
                        <i:InvokeCommandAction Command="{Binding EventMouseOver}" 
                                               CommandParameter="{Binding ElementName=exit}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <i:InvokeCommandAction Command="{Binding MouseLeaveButton}" 
                                               CommandParameter="{Binding ElementName=exit}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseDown">
                        <i:InvokeCommandAction Command="{Binding ExitButtonCommand}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBlock>
        </StackPanel>
    </Grid>
</Window>

这是ViewModel

using SilentUpdate.Helpers;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace SilentUpdate.ViewModels
{
    public class MainViewModel : INotifyPropertyChanged
    {
        #region Property change interface implement
        public event PropertyChangedEventHandler PropertyChanged;

        private void RaiseProperChanged (string prop)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(prop));
            }
        }
        #endregion

        #region Button Status
        // To keep track the active click button
        private TextBlock activeButton;
        private Brush homeColor;
        private bool previewStatus, runStatus, saveStatus;

        public Brush HomeColor
        {
            get { return this.homeColor; }
            set { this.homeColor = value; RaiseProperChanged("HomeColor"); }
        }

        public bool PreviewStatus
        {
            get { return this.previewStatus; }
            set
            {
                this.previewStatus = value;
                RaiseProperChanged("PreviewStatus");
            }
        }

        public bool RunStatus
        {
            get { return this.runStatus; }
            set
            {
                this.runStatus = value;
                RaiseProperChanged("RunStatus");
            }
        }

        public bool SaveStatus
        {
            get { return this.saveStatus; }
            set
            {
                this.saveStatus = value;
                RaiseProperChanged("SaveStatus");
            }
        }
        #endregion

        #region Event Binding        
        // Command for binding to the event
        private ICommand exitButtonCommand, eventMouseOver, eventMouseLeave;
        private ICommand homeCommand, settingCommand, previewCommand, runCommand, saveCommand;

        private bool canExecute = true;                  

        public bool CanExecute
        {
            get { return this.canExecute; }
            set
            {
                if (this.canExecute == value)
                {
                    return;
                }
                this.canExecute = value;
            }
        }

        /// <summary>
        /// Public for binding to Exit button
        /// </summary>
        public ICommand ExitButtonCommand
        {
            get { return this.exitButtonCommand; }
            set
            {
                this.exitButtonCommand = value;
            }
        }

        /// <summary>
        /// Exit the application when Exit button click binding to ExitButtonCommand
        /// </summary>
        /// <param name="obj"></param>
        public void ExitApp(object obj)
        {
            Application.Current.Shutdown();
        }

        /// <summary>
        /// Public for binding to Home button
        /// </summary>
        public ICommand HomeCommand
        {
            get { return this.homeCommand; }
            set
            {
                this.homeCommand = value;
            }
        }

        /// <summary>
        /// Actual home event, will display the home page
        /// This will update the page binding variable
        /// </summary>
        /// <param name="obj"></param>
        public void HomeEvent (object obj)
        {
            // Change the active button
            ChangeActive((TextBlock)obj);
            // Change the button status
            PreviewStatus = false;
            RunStatus = false;
            SaveStatus = false;
            HomeColor = new SolidColorBrush(Colors.White);
            MessageBox.Show("HomeEvent");
        }

        /// <summary>
        /// Public for binding to Setting button
        /// </summary>
        public ICommand SettingCommand
        {
            get { return this.settingCommand; }
            set
            {
                this.settingCommand = value;
            }
        }

        /// <summary>
        /// Actual Setting event, will display the setting page
        /// This will update the page binding variable
        /// </summary>
        /// <param name="obj"></param>
        public void SettingEvent(object obj)
        {
            // Change the active button
            ChangeActive((TextBlock)obj);
            // Change the button status
            PreviewStatus = true;
            RunStatus = false;
            SaveStatus = false;
            MessageBox.Show("SettingEvent");
        }

        /// <summary>
        /// Public for binding to Preview button
        /// </summary>
        public ICommand PreviewCommand
        {
            get { return this.previewCommand; }
            set
            {
                this.previewCommand = value;
            }
        }

        /// <summary>
        /// Actual Preview event, will display the preview page
        /// based on the Messenger sending to the page for the environment 
        /// setting by the setting page        
        /// This will update the page binding variable
        /// </summary>
        /// <param name="obj"></param>
        public void PreviewEvent(object obj)
        {
            // Change the active button
            ChangeActive((TextBlock)obj);
            // Change the button status
            PreviewStatus = true;
            RunStatus = true;
            SaveStatus = false;
            MessageBox.Show("PreviewEvent");
        }

        /// <summary>
        /// Public for binding to Run button
        /// </summary>
        public ICommand RunCommand
        {
            get { return this.runCommand; }
            set
            {
                this.runCommand = value;
            }
        }

        /// <summary>
        /// Actual Preview event, will display the after run page
        /// based on the Messenger sending to the page for the environment 
        /// setting by the setting page and the selection of the list file
        /// from the Preview page
        /// This will update the page binding variable
        /// </summary>
        /// <param name="obj"></param>
        public void RunEvent(object obj)
        {
            // Change the active button
            ChangeActive((TextBlock)obj);
            // Change the button status
            PreviewStatus = true;
            RunStatus = true;
            SaveStatus = true;
            MessageBox.Show("RunEvent");
        }

        /// <summary>
        /// Public for binding to Save button
        /// </summary>
        public ICommand SaveCommand
        {
            get { return this.saveCommand; }
            set
            {
                this.saveCommand = value;
            }
        }

        /// <summary>
        /// Actual Save event, will generate the PDF file log
        /// And launch the PDF file based on default application setting
        /// </summary>
        /// <param name="obj"></param>
        public void SaveEvent(object obj)
        {
            ChangeActive((TextBlock)obj);
            MessageBox.Show("SaveEvent");
        }

        /// <summary>
        /// This event uses by all button to change color to active state
        /// </summary>
        public ICommand EventMouseOver
        {
            get { return this.eventMouseOver; }
            set
            {
                this.eventMouseOver = value;
            }
        }

        /// <summary>
        /// Actual mouse enter event for binding command EventMouseOver
        /// </summary>
        /// <param name="obj">The target object of button</param>
        public void MouseOverButton(object obj)
        {
            // Casting the object
            TextBlock target = (TextBlock)obj;
            if (activeButton == null)
            {
                // High light target 
                activeButton = target;
            }
            // High light target 
            HighLightText(target, true);
        }

        /// <summary>
        /// This event uses by all button to change color to inactive state
        /// </summary>
        public ICommand EventMouseLeave
        {
            get { return this.eventMouseLeave; }
            set { this.eventMouseLeave = value; }
        }

        /// <summary>
        /// Actual mouse leave event for binding command EventMouseLeave
        /// </summary>
        /// <param name="obj">The target object of button</param>
        private void MouseLeaveButton(object obj)
        {
            // Casting the object
            TextBlock target = (TextBlock)obj;
            if (target.Equals(activeButton) == false)
            {
                HighLightText(target, false);
            }
            HighLightText(activeButton, true);
        }           

        /// <summary>
        /// Update the canExecute property
        /// </summary>
        /// <param name="obj"></param>
        public void ChangeCanExecute(object obj)
        {
            canExecute = !canExecute;
        }
        #endregion

        #region Constructor
        public MainViewModel()
        {
            exitButtonCommand = new RelayCommand(ExitApp, Param => this.canExecute);
            eventMouseOver = new RelayCommand(MouseOverButton);
            eventMouseLeave = new RelayCommand(MouseLeaveButton);
            homeCommand = new RelayCommand(HomeEvent);
            settingCommand = new RelayCommand(SettingEvent);
            previewCommand = new RelayCommand(PreviewEvent);
            runCommand = new RelayCommand(RunEvent);
            saveCommand = new RelayCommand(SaveEvent);
            // Set the Preview status disable when start
            PreviewStatus = false;
            // Set the Run status disable when start
            RunStatus = false;
            // Set the Save status disable when start
            SaveStatus = false;
            // HomeColor
            HomeColor = new SolidColorBrush(Colors.White);
        }
        #endregion

        #region Private Helper
        private void HighLightText(TextBlock target, bool isHighlight)
        {
            if (isHighlight)
            {
                target.Foreground = new SolidColorBrush(Colors.White);
            }
            else
            {
                target.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromArgb(68, 173, 173, 173));
            }
        }

        private void ChangeActive (TextBlock target)
        {
            if (activeButton != null)
            {
                HighLightText(activeButton, false);
            }
            activeButton = target;
            HighLightText(activeButton, true);
            activeButton.ReleaseMouseCapture();
            target.ReleaseMouseCapture();
            HomeColor = new SolidColorBrush(System.Windows.Media.Color.FromArgb(68, 173, 173, 173));
        }
        #endregion
    }
}

1 个答案:

答案 0 :(得分:0)

我对实现的错误,我应该将UI逻辑保留在view而不是viewmodel中。这解决了问题