Как показать Messagebox в MVVM

Возможный дубликат:
Как вы успешно реализовали функцию MessageBox.Show() в MVVM?

Я хочу показать окно сообщения в приложении MVVM MVVM. поэтому от куда вызвать MessageBox.Show().

Ответы

Ответ 1

В Windows Forms или WPF без MVVM вы можете просто сказать MessageBox.Show(), и это все! Было бы неплохо, если бы вы могли сделать то же самое в MVVM?

Вот один из способов сделать это - и он как можно ближе к MessageBox.Show().

Вот дружественный 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
        }
    }
}

Тада!

Вот как это работает:

Все, что действительно делает MessageBox_Show, это пожар, поэтому он отлично подходит для MVVM. ViewModel ничего не знает о каком-либо представлении, которое может или не может его потреблять, и оно не отображает Windows MessageBox на своем собственном уровне, поэтому его также можно безопасно протестировать.

Чтобы использовать его в представлении, которое вызовет фактическое отображение MessageBox, вы просто подписаны на событие и вызовите e.Show() в обработчике событий, например:

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

И это все, что вам нужно сделать, чтобы показать совместимые с MVVM Windows MessageBoxes.

Код ниже должен быть реализован только один раз в вашем проекте или вы можете поместить его в многоразовую разделяемую библиотеку.

Добавьте это в свой базовый класс ViewModel, чтобы он мог использоваться из любого 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));
        }
    }
}

Затем добавьте класс EventArgs для обработчика событий:

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

Тестирование модулей легко:

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

Счастливое кодирование!

Ответ 2

Я обнаружил, что MVVM вызывает последовательность OCD в программистах (я знаю по опыту). Это хорошо. Но для некоторых вещей усилия просто не стоят того, особенно если он вводит полный порядок сложности, чтобы спросить пользователя "Вы уверены, что хотите xxxx?"

Мое мнение таково, что MessageBox.Show() можно вызывать из кода, но никогда не ViewModel. Пока диалоговые окна не интегрируются лучше с XAML, просто возьмите удар и не чувствуйте себя плохо. Это действительно серая область текущего состояния дизайна интерфейса WPF.