2010-09-14 20 views
13

Powiel możliwe:
How have you successfully implemented MessageBox.Show() functionality in MVVM?jak pokazać MessageBox w MVVM

chcę pokazać okno komunikatu w mojej aplikacji MVVM WPF. , aby skąd wywołać MessageBox.Show().

+0

dziękuję, że bardzo mi pomogło –

+1

To jest mocno odrzucone i oznaczone jako duplikat, ale jest to również najwyższy wynik Google dla 'mvvm messagebox wpf' ... – Benjol

+0

Po prostu mówienie ... może nie być tak piękne czy jak, ale ty może po prostu wywołać System.Windows.MessageBox.Show (params); od .. dowolnej klasy. – Para

Odpowiedz

6

Zauważyłem, że MVVM wywołuje pasmo OCD u programistów (wiem z doświadczenia). To dobra rzecz. Ale dla niektórych rzeczy wysiłek po prostu nie jest tego wart, zwłaszcza jeśli wprowadza całą złożoność tylko po to, aby zapytać użytkownika "Czy na pewno chcesz xxxx?"

Moim zdaniem jest to, że MessageBox.Show() może być wywoływana z poziomu kodu, ale nigdy ViewModel. Dopóki okna dialogowe nie będą lepiej zintegrowane z XAML, po prostu weźcie udział w akcji i nie czujcie się źle. To naprawdę szara strefa obecnego stanu projektu interfejsu użytkownika WPF.

+2

Używam polecenia, więc jeśli będę musiał pokazać okno komunikatu po tym jak przycisk może wykonać i wykonać funkcję, muszę przekazać niektóre dane do kod widoku za plikiem, a następnie przerwie mvvm. –

13

W Windows Forms lub WPF bez MVVM można po prostu powiedzieć MessageBox.Show() i to było to! Czy nie byłoby miło, gdybyś mógł zrobić to samo w MVVM?

Oto jeden sposób, aby to zrobić - i jest tak blisko, jak mogę dostać się do MessageBox.Show().

Tutaj jest przyjazny dla MVVM MessageBox_Show()!

public class MyViewModel: ViewModelBase 
{ 
    protected void AskTheQuestion() 
    { 
     MessageBox_Show(ProcessTheAnswer, "Are you sure you want to do this?", "Alert", System.Windows.MessageBoxButton.YesNo); 
    } 

    public void ProcessTheAnswer(MessageBoxResult result) 
    { 
     if (result == MessageBoxResult.Yes) 
     { 
      // Do something 
     } 
    } 
} 

Tada!

Oto jak to działa:

Wszystko to MessageBox_Show faktycznie robi to ogień zdarzenie, więc doskonale MVVM obsłudze. ViewModel nie wie nic o widoku, który może, ale nie musi, pochłaniać go, i nie wykonuje demonstracji Windows MessageBox na swoim, więc może być bezpiecznie testowany w jednostce.

Aby użyć go w widoku, który spowoduje, że faktycznie pokazać MessageBox, wystarczy zapisać się do imprezy i zadzwoń e.Show() w procedurze obsługi zdarzenia tak:

public partial class MyView : UserControl 
{ 
    public MyView() 
    { 
     InitializeComponent(); 

     this.DataContext = new MyViewModel(); 
     (this.DataContext as MyViewModel).MessageBoxRequest += new EventHandler<MvvmMessageBoxEventArgs>(MyView_MessageBoxRequest); 
    } 

    void MyView_MessageBoxRequest(object sender, MvvmMessageBoxEventArgs e) 
    { 
     e.Show(); 
    } 
} 

I to wszystko, co musisz zrobić, aby pokazać przyjazne dla MVVM Windows MessageBoxes.

Poniższy kod należy zaimplementować tylko raz w projekcie lub można go umieścić w udostępnianej bibliotece wielokrotnego użytku.

Dodaj to do swojej klasy bazowej ViewModel dzięki czemu może być używany z dowolnym ViewModel:

public class ViewModelBase : INotifyPropertyChanged 
{ 
    //... 

    public event EventHandler<MvvmMessageBoxEventArgs> MessageBoxRequest; 
    protected void MessageBox_Show(Action<MessageBoxResult> resultAction, string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None) 
    { 
     if (this.MessageBoxRequest != null) 
     { 
      this.MessageBoxRequest(this, new MvvmMessageBoxEventArgs(resultAction, messageBoxText, caption, button, icon, defaultResult, options)); 
     } 
    } 
} 

a następnie dodać klasę EventArgs do obsługi zdarzeń:

public class MvvmMessageBoxEventArgs : EventArgs 
{ 
    public MvvmMessageBoxEventArgs(Action<MessageBoxResult> resultAction, string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None) 
    { 
     this.resultAction = resultAction; 
     this.messageBoxText = messageBoxText; 
     this.caption = caption; 
     this.button = button; 
     this.icon = icon; 
     this.defaultResult = defaultResult; 
     this.options = options; 
    } 

    Action<MessageBoxResult> resultAction; 
    string messageBoxText; 
    string caption; 
    MessageBoxButton button; 
    MessageBoxImage icon; 
    MessageBoxResult defaultResult; 
    MessageBoxOptions options; 

    public void Show(Window owner) 
    { 
     MessageBoxResult messageBoxResult = MessageBox.Show(owner, messageBoxText, caption, button, icon, defaultResult, options); 
     if (resultAction != null)resultAction(messageBoxResult); 
    } 

    public void Show() 
    { 
     MessageBoxResult messageBoxResult = MessageBox.Show(messageBoxText, caption, button, icon, defaultResult, options); 
     if (resultAction != null) resultAction(messageBoxResult); 
    } 
} 

Testowanie jednostkowe jest proste:

target.AskTheQuestion(); 
target.ProcessTheAnswer(System.Windows.MessageBoxResult.Yes); 

Happy Coding!

+0

Bardzo przydatne! Dzięki – Latrova

+0

Dobra implementacja, ponieważ używa zdarzeń, to z pewnością spowoduje wyciek pamięci, szczególnie gdy masz dużo widoków. –

+0

Ale używając odwołań do System.Windows w ViewModelBase dla MessageBoxResult, MessageBoxOptions czy nie pokonujesz celu MVVM? –