Thang_Duong Ответов: 1

События в XAML в WPF mouseleave не стреляли в команде обязательны


Я запустил проект MVVM и установил привязку представления ко всем событиям в текстовом блоке из ViewModel. Я установил 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"></res:String>
                <res:String x:Key="settingsIcon"></res:String>
                <res:String x:Key="previewIcon"></res:String>
                <res:String x:Key="runIcon"></res:String>
                <res:String x:Key="saveIcon"></res:String>
                <res:String x:Key="exitIcon"></res:String>
                <res:String x:Key="warningIcon"></res:String>
                <res:String x:Key="folderIcon"></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>


А вот моя модель представления
using SilentUpdate.Helpers;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
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;
        }

        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);
        }

        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));
        }
    }
}


Что я уже пробовал:

Попробуйте изменить событие MouseLeave из LostFocus, но никакой помощи

1 Ответов

Рейтинг:
10

Graeme_Grant

У меня есть проблема с вашим пониманием MVVM. У вас есть код пользовательского интерфейса в ViewModel (VM), где он не принадлежит. Весь код пользовательского интерфейса принадлежит странице XAML & amp;/или коду страницы XAML.

Подумайте о виртуальных машинах как о слабо связанном слое между вашими данными и пользовательским интерфейсом - он ничего не знает о самом пользовательском интерфейсе, только о данных. Более официальным описанием было бы: "Модель представления-это абстракция представления, предоставляющая общедоступные свойства и команды. В виртуальной машине также можно было бы описать состояние данных в модели".

если вы не хотите помещать логику пользовательского интерфейса в код позади, у вас есть другие доступные варианты. Например: если вы устанавливаете цвет на основе состояния, то ValueConverter или MultiValueConverter в переплете был бы хороший выбор.

Behaviors хороши для более сложных требований, чем ValueConverter предложения. Например, у меня есть GridHelpers поведение, которое помогает мне генерировать Grid.Row &усилитель; Grid.Colums динамически с калибровкой в ItemPanel в ItemsControl Виртуальная машина совершенно не знает об этом, все, что делает виртуальная машина, - это выставляет OnservableCollection данных.

Есть и другие методы, которые, я уверен, другие будут использовать, однако эти два будут соответствовать 100% вашим требованиям к коду сверху.

Для пуговиц я бы привязался к Click событие, а не MouseDown событие. MouseEnter, MouseLeave, MouseDown триггерные события для изменения состояния пользовательского интерфейса должны оставаться в XAML, а не в виртуальной машине. Если вы не хотите делать это в XAML, то привязывайтесь к событиям в коде, где находится любой код пользовательского интерфейса.


Thang_Duong

Большое спасибо. Моя ошибка, что я должен оставить логику пользовательского интерфейса в представлении не модель представления

Graeme_Grant

Все хорошо ... часть процесса обучения. Мы все через это проходим. Просто рад, что смог помочь. :)