Подтвердить что ты не робот

Как вы успешно реализовали функцию MessageBox.Show() в MVVM?

У меня есть приложение WPF , которое вызывает MessageBox.Show() обратно в ViewModel (чтобы проверить, действительно ли пользователь хочет удалить). Это действительно работает, но идет против зерна MVVM, поскольку ViewModel не должен явно определять, что происходит в представлении.

Итак, теперь я думаю, что как лучше всего реализовать функцию MessageBox.Show() в моем приложении MVVM, параметры:

  • У меня могло бы быть сообщение с текстом "Вы уверены...?" наряду с двумя кнопками "Да" и "Нет" на границе в моем XAML и создайте триггер на шаблоне, чтобы он был свернут/виден на основе ViewModelProperty, называемого AreYourSureDialogueBoxIsVisible, а затем, когда мне нужен этот диалог box, присвойте AreYourSureDialogueBoxIsVisible значение "true", а также обработайте две кнопки через DelegateCommand обратно в моей ViewModel.

  • Я мог бы как-то попытаться обработать это с помощью триггеров в XAML, чтобы кнопка Delete фактически просто создавала элемент Border с сообщением и кнопками в нем, а кнопка Yes действительно удаляла.

Оба решения кажутся слишком сложными для того, что раньше было рядом строк кода с MessageBox.Show().

Каким образом вы успешно реализовали диалоговые окна в ваших MVVM-приложениях?

4b9b3361

Ответ 1

Из двух вы упомянули, я предпочитаю вариант № 2. Кнопка "Удалить" на странице просто заставляет "Подтвердить диалог удаления". Диалоговое окно "Подтвердить удаление" фактически отменяет удаление.

Вы проверили Karl Shifflett WPF Line Business Slides and Demos? Я знаю, что он делает что-то подобное. Я постараюсь запомнить, где.

EDIT: ознакомьтесь с демонстрацией № 11 "Проверка данных в MVVM" (EditContactItemsControlSelectionViewModel.DeleteCommand). Карл называет всплывающее окно из ViewModal (What!?:-). Мне больше нравится ваша идея. Кажется, проще Unit Test.

Ответ 2

Службы на помощь. Используя Onyx (отказ от ответственности, я автор) это так же просто, как:

public void Foo()
{
    IDisplayMessage dm = this.View.GetService<IDisplayMessage>();
    dm.Show("Hello, world!");
}

В запущенном приложении это косвенно вызовет MessageBox.Show( "Hello, world!" ). При тестировании службы IDisplayMessage можно высмеять и предоставить ViewModel для выполнения того, что вы хотите выполнить во время теста.

Ответ 3

Я просто создаю интерфейс (IMessageDisplay или аналогичный), который вводится в виртуальную машину, и он имеет такие методы, как MessageBox (ShowMessage() и т.д.). Вы можете реализовать это, используя стандартный почтовый ящик или что-то большее, чем WPF (я использую этот на CodePlex какой-то парень по имени Prajeesh).

Таким образом, все разделено и проверяемо.

Ответ 4

Как насчет создания события типа "MessageBoxRequested", которое обрабатывается в кодовой форме представления (в любом случае это просмотр только кода, поэтому я не вижу проблемы с тем, что этот код имеет код).

Ответ 5

Чтобы развернуть на Dean Chalk, ответьте, что его ссылка kaput:

В файле App.xaml.cs мы подключаем диалог подтверждения к viewmodel.

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    var confirm = (Func<string, string, bool>)((msg, capt) => MessageBox.Show(msg, capt, MessageBoxButton.YesNo) == MessageBoxResult.Yes);
    var window = new MainWindowView();
    var viewModel = new MainWindowViewModel(confirm);
    window.DataContext = viewModel;
    ...
}

В представлении (MainWindowView.xaml) у нас есть кнопка, которая вызывает команду в ViewModel

<Button Command="{Binding Path=DeleteCommand}" />

В viewmodel (MainWindowViewModel.cs) используется команда делегата, чтобы показать "Вы уверены?". диалога и выполнить действие. В этом примере это SimpleCommand похожее на this, но любая реализация ICommand должна делать.

private readonly Func<string, string, bool> _confirm;

//constructor
public MainWindowViewModel(Func<string, string, bool> confirm)
{
    _confirm = confirm;
    ...
}

#region Delete Command
private SimpleCommand _deleteCommand;
public ICommand DeleteCommand
{
    get { return _deleteCommand ?? (_deleteCommand = new SimpleCommand(ExecuteDeleteCommand, CanExecuteDeleteCommand)); }
}

public bool CanExecuteDeleteCommand()
{
    //put your logic here whether to allow deletes
    return true;
}

public void ExecuteDeleteCommand()
{
    bool doDelete =_confirm("Are you sure?", "Confirm Delete");
    if (doDelete)
    {
        //delete from database
        ...
    }
}
#endregion

Ответ 7

Я реализовал поведение, которое прослушивает сообщение из ViewModel. Это основано на решении Laurent Bugnion, но поскольку он не использует код и больше подходит для повторного использования, я считаю его более элегантным.

Проверьте здесь

Ответ 9

На всякий случай кто-то еще читает и неудовлетворен:

Я просто хотел обработать "MessageBox" типа "уведомления" (то есть меня не волнует DialogResult), но проблема, с которой я сталкиваюсь в большинстве решений, о которых я читал, состоит в том, что они, по-видимому, косвенно вынуждают вас выберите свою реализацию вида (то есть, в настоящее время у меня есть MessageBox.Show, но если я позже решу просто поиграть с видимостью скрытой панели непосредственно в моем представлении, это не будет очень хорошо связано с интерфейсом INotification в ViewModel).

Итак, я пошел быстро и грязно:

ViewModel имеет свойство string NotificationMessage, с изменениями, уведомленными о PropertyChanged.

The View подписывается на PropertyChanged, и если он видит свойство NotificationMessage, он делает все, что захочет.

ОК, поэтому это означает, что View имеет код-позади, а имя PropertyChanged жестко закодировано, но в любом случае оно будет жестко закодировано в XAML. И это означает, что я избегаю всех таких вещей, как конвертеры для видимости, и свойства, чтобы сказать, остается ли уведомление все еще видимым или нет.

(По общему признанию, это просто ограниченный случай использования (огонь и забыть), я не думал о том, как я могу его расширить.)

Ответ 10

Я просто выброшу его из виртуальной машины. Я не хочу использовать чужую службу или написать свой собственный, просто чтобы бросить сообщение.

Ответ 11

Недавно я столкнулся с этой проблемой, когда мне пришлось заменить MessageBox.Show в ViewModels некоторым механизмом механизма сообщения с жалобами MVVM.

Для этого я использовал InteractionRequest<Notification> и InteractionRequest<Confirmation> вместе с триггерами взаимодействия и написал свои собственные представления для окна сообщения.

Я опубликовал здесь

Ответ 12

В этой теме так много ответов, которые варьируются от создания пользовательского класса до использования сторонних библиотек. Я бы сказал, пользуюсь сторонней библиотекой, если вам нужны крутые всплывающие окна с приятными визуальными эффектами.

Но если вы просто хотите использовать регулярное окно сообщений из microsoft для своего приложения WPF, то это совместимая с MVVM/unit версия:

Первоначально я думал, что просто унаследовал бы от окна сообщения и обернул бы его интерфейсом, но я не мог из-за того, что окно Message не имело публичного конструктора, так что вот "простое" решение:

Декомпиляция окна сообщений в visual studio вы можете увидеть все перегрузки метода, я проверил, какие из них я хотел, а затем создал новый класс и добавил методы, завернул его с интерфейсом и ta-da! Теперь вы можете использовать ninject для привязки интерфейса и класса, вставлять его и использовать Moq для модульного тестирования и т.д.

Создайте интерфейс (добавьте несколько перегрузок, поскольку они мне не нужны):

public interface IMessageBox
    {
        /// <summary>Displays a message box that has a message, title bar caption, and button; and that returns a result.</summary>          
        MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button);

        /// <summary>Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.</summary>           
        MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon);

        /// <summary>Displays a message box that has a message and title bar caption; and that returns a result.</summary>            
        MessageBoxResult Show(string messageBoxText, string caption);
    }

Тогда у нас есть класс, который наследует от него:

public class MessageBoxHelper : IMessageBox
    {
        /// <summary>Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.</summary>            
        public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button,
            MessageBoxImage icon)
        {
            return MessageBox.Show(messageBoxText, caption, button, icon, MessageBoxResult.None,
                MessageBoxOptions.None);
        }

        /// <summary>Displays a message box that has a message, title bar caption, and button; and that returns a result.</summary>            
        public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button)
        {
            return MessageBox.Show(messageBoxText, caption, button, MessageBoxImage.None, MessageBoxResult.None,
                MessageBoxOptions.None);
        }

        /// <summary>Displays a message box that has a message and title bar caption; and that returns a result.</summary>            
        public MessageBoxResult Show(string messageBoxText, string caption)
        {
            return MessageBox.Show(messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None,
                MessageBoxResult.None, MessageBoxOptions.None);
        }

        /// <summary>Displays a message box that has a message and that returns a result.</summary>           
        public MessageBoxResult Show(string messageBoxText)
        {
            return MessageBox.Show(messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None,
                MessageBoxResult.None, MessageBoxOptions.None);
        }
    }

Теперь просто используйте это при инъекциях и т.д., И бум у вас есть фальшивая абстракция, которая будет делать трюк... что отлично в зависимости от того, где вы будете его использовать. Мое дело - простое приложение, предназначенное только для того, чтобы сделать несколько вещей, поэтому не стоит конструировать решение. Надеюсь, это поможет кому-то.