2014-05-12 14 views
5

W aplikacji WPF wraz z MVVMLight Toolkit, chciałbym zobaczyć twoją opinię, jaki jest najlepszy sposób wdrożenia, jeśli muszę anulować zdarzenie Zamknij okno. W zdarzeniu Window.Closing mogę ustawić e.Cancel = true, co uniemożliwia zamknięcie formularza. Aby określić, czy zamknięcie jest dozwolone, czy też można mu zapobiec, należy to zrobić w kontekście ViewModel.WPF MVVM anulować Window.Closing event

Jednym z rozwiązań może być, jeśli zdefiniuję zmienną Application i mogę zapytać o to w zwykłym module obsługi zdarzeń w kodzie widoku?

dzięki

+0

W normalnej MVVM jest to proste z dołączoną właściwością. Nie wiadomo, jak to działa z MVVMLight choć ... –

Odpowiedz

11

Z MVVM Światła masz EventToCommand:

więc można w XAML drutu up imprezy zamykającej do VM.

<Window ... 
     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
     xmlns:command="http://www.galasoft.ch/mvvmlight"> 
<i:Interaction.Triggers> 
    <i:EventTrigger EventName="Closing"> 
    <command:EventToCommand Command="{Binding ClosingCommand}" 
          PassEventArgsToCommand="True" /> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

aw VM:

public RelayCommand<CancelEventArgs> ClosingCommand { get; private set; } 

ctor() { 
    ClosingCommand = new RelayCommand<CancelEventArgs>(args => args.Cancel = true); 
} 

Jeśli nie chcesz przekazać CancelEventArgs do VM:

Można zawsze przyjmuje podobne podejście z Behavior i po prostu użyć prosty bool z VM (powiązanie tego bool z Zachowaniem), aby wskazać, że zdarzenie zamknięcia powinno zostać anulowane.

Aktualizacja:

Download Link for following example

Aby to zrobić z Behavior można tylko mieć Behavior takich jak:

internal class CancelCloseWindowBehavior : Behavior<Window> { 
    public static readonly DependencyProperty CancelCloseProperty = 
    DependencyProperty.Register("CancelClose", typeof(bool), 
     typeof(CancelCloseWindowBehavior), new FrameworkPropertyMetadata(false)); 

    public bool CancelClose { 
    get { return (bool) GetValue(CancelCloseProperty); } 
    set { SetValue(CancelCloseProperty, value); } 
    } 

    protected override void OnAttached() { 
    AssociatedObject.Closing += (sender, args) => args.Cancel = CancelClose; 
    } 
} 

Teraz w XAML:

<i:Interaction.Behaviors> 
    <local:CancelCloseWindowBehavior CancelClose="{Binding CancelClose}" /> 
</i:Interaction.Behaviors> 

Gdzie CancelClose jest właściwością bool z VM, która wskazuje, czy zdarzenie Closing powinno zostać anulowane, czy też nie. W załączonym przykładzie mam Button, aby włączyć tę bool z VM, które powinny pozwolić przetestować Behavior

+0

Tak, to może być rozwiązanie, ale chciałbym zachować przewagę MVVM, aby oddzielić widok i model tak bardzo, jak to tylko możliwe. Jak radzić sobie z tym z zachowaniem? Jeśli używam wartości bool, zdarzenie zamknięcia okna może zostać anulowane? – pillesoft

+0

@ pillesoft Sprawdź aktualizację na końcu odpowiedzi, aby zobaczyć przykład z "Zachowaniem".Istnieje również link do pobrania, który powinien dać ci przykład w projekcie do przetestowania. Jedną rzeczą, o której należy pamiętać, jest to, że główną zaletą MVVM w porównaniu do wzorców takich jak MVC jest umożliwienie testowania jednostki VM. Jeśli więc możesz przetestować swoją logikę w VM grzywnie (którą możesz w tym przypadku z jednostkowym testowym projektem), osobiście nie nazwałbym tego podejścia jako błędnego. – Viv

+0

Czy mogę użyć podejścia światła MVVM do przekazania argumentu wzdłuż zdarzenia eventArgs? mdziadowiec

0

Można by kontrolować to za pomocą Messages, na przykład:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     Messenger.Default.Register<CloseApplicationMessage>(this, m => Close()); 
     Loaded += MainWindowLoaded; 
     Closing += MainWindowClosing; 
    } 

    private void MainWindowClosing(object sender, CancelEventArgs e) 
    { 
     //Ask for saving 
     var closingMessage = new ClosingApplicationMessage(); 
     Messenger.Default.Send(closingMessage); 
     if (closingMessage.Cancel) 
      e.Cancel = true; 
    } 
... 

Komunikat MVVM:

public class ClosingApplicationMessage 
{ 
    public bool Cancel { get; set; } 
} 

W ten sposób, w dowolnym miejscu, w którym słuchasz ClosingApplicationMessage, możesz kontrolować, kiedy aplikacja ma zostać zamknięta, i możesz ją anulować. Mam nadzieję, że to pomoże ...