2015-08-03 10 views
3

Я знаю, что этот вопрос задан много раз, но я постараюсь быть конкретным, насколько это возможно.Как правильно обрабатывать событие закрытия окна в wpf MVVM

Я новичок в WPF/MVVM и используя MVVM Light Toolkit от Galasoft в своем проекте.

У меня есть вид, содержащий форму, в которой пользователь вводит некоторые данные о пациенте. Когда они нажимают кнопку закрытия (X), я хочу проверить, что они что-то ввели, и если да, спросите их, хотят ли они сохранить до закрытия с помощью (Да, Нет и Отменить). Я сделал некоторые исследования и обнаружили, что многие предполагают функцию EventToCommand как так,

XAML

<Window 
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF45" 
    DataContext="{Binding Main, Source={StaticResource Locator}}"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Closing"> 
     <cmd:EventToCommand Command="{Binding OnClosingCommand}" 
      PassEventArgsToCommand="True"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
... 
</Window> 

View Model

public class MainViewModel : ViewModelBase 
{ 
    public RelayCommand<CancelEventArgs> OnClosingCommand { get; set; } 

    public MainViewModel() 
    { 
     this.OnClosingCommand = 
     new RelayCommand<CancelEventArgs>(this.OnClosingCommandExecuted); 
    } 

    private void OnClosingCommandExecuted(CancelEventArgs cancelEventArgs) 
    { 
     // logic to check if view model has updated since it is loaded 
     if (mustCancelClosing) 
     { 
     cancelEventArgs.Cancel = true; 
     } 
    } 
} 

Приведенный выше пример взят из Confirmation when closing window with 'X' button with MVVM light

Однако создатель MVVM L Сам Инструментарий говорит, что это нарушает разделение беспокойства, которое пытается создать шаблон MVVM, поскольку он передает аргументы события, принадлежащие представлению (в данном случае CancelEventArgs) модели представления. Он так сказал в этой статье http://blog.galasoft.ch/posts/2014/01/using-the-eventargsconverter-in-mvvm-light-and-why-is-there-no-eventtocommand-in-the-windows-8-1-version/

Итак, мой вопрос: как правильно обращаться с такой проблемой, которая не нарушает шаблон MVVM. Любая точка в правильном направлении была бы очень признательна!

ответ

1

Я не претендую на абсолютную истину, но мне нравится следующий подход.
вид модели Основание имеет RelayCommand/DelegateCommand так:

public ICommand ClosingCommand { get; } 

, где ICommand.Execute реализован как:

/// <summary> 
    /// Executes an action, when user closes a window, displaying this instance, using system menu. 
    /// </summary> 
    protected virtual void Closing() 
    { 
    } 

и ICommand.CanExecute как:

/// <summary> 
    /// Detects whether user can close a window, displaying this instance, using system menu. 
    /// </summary> 
    /// <returns> 
    /// <see langword="true"/>, if window can be closed; 
    /// otherwise <see langword="false"/>. 
    /// </returns> 
    protected virtual bool CanClose() 
    { 
     return true; 
    } 

В свою очередь, интерфейс использует прикрепленный поведение для обработки Window.Closing:

public static class WindowClosingBehavior 
{ 
     public static readonly DependencyProperty ClosingProperty = DependencyProperty.RegisterAttached(
      "Closing", 
      typeof(ICommand), 
      typeof(WindowClosingBehavior), 
      new UIPropertyMetadata(new PropertyChangedCallback(ClosingChanged))); 

     private static void ClosingChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
     { 
      var window = target as Window; 
      if (window != null) 
      { 
       if (e.NewValue != null) 
        window.Closing += Window_Closing; 
       else 
        window.Closing -= Window_Closing; 
      } 
     } 

     private static void Window_Closing(object sender, CancelEventArgs e) 
     { 
      var window = sender as Window; 
      if (window != null) 
      { 
       var closing = GetClosing(window); 
       if (closing != null) 
       { 
        if (closing.CanExecute(null)) 
         closing.Execute(null); 
        else 
         e.Cancel = true; 
       } 
      } 
     } 
} 

XAML (предполагает, что вид модель является DataContext для окна):

behaviors:WindowClosingBehavior.Closing="{Binding ClosingCommand}" 
Смежные вопросы