Страницы

Поиск по вопросам

вторник, 17 декабря 2019 г.

Как сделать диалоговое окно?

#c_sharp #wpf #mvvm


Предположим есть окно в котором в виде таблице отображается некий список, для каждой
записи есть некий набор действий, для примера пусть будут "Edit"/"Detail"/"Delete".

При выборе пользователем пункта "Delete" необходимо показать окно с неким предупреждающим
текстом, и двумя возможными действиями: "Ok"/"Cancel".

Как бы я это сделал в winforms приложении:

var dialogBox = new DialogBox.ShowModal();
if(dialogBox.DialogResult == DialogResult.Ok)
{
    //здесь код который должен быть сделан в случае подтверждения действия
}
//здесь то что надо сделать в случае отмены


В рамках mvvm, необходимо сделать View, ModelView, т.е. у нас должно быть что то
типа Main, MainViewModel, Dialog, DialogViewModel;

в Main - будут кнопки которые будут прибиндины к командам из ViewModel. т.е. например
так могла бы выглядеть команда для "Delete":

private void Delete()
{
    var dialog = new Dialog(new DialogViewModel())
    dialog.Show();
    //здесь как то надо сделать проверку на то что случилось в диалоге
}


Как вариант можно сделать публичное свойство в DialogViewModel с типом boolean и
устанавливать его в диалоге, по нажатии на любую из кнопок (Ok/Canсel) менять его значение,
в главной форме смотреть значение этого свойства. Вот только меня терзают сомнения
в правильности такого подхода.

Как сделать Диалоговое окно в wpf с использованием mvvm?

P.S.: код писал здесь, могут быть ошибки
    


Ответы

Ответ 1



Здесь есть два варианта действий: Более простой способ, но более неудобный в случае, если вы используете TDD: Вам нет необходимости создавать ViewModel и View отдельно для диалогового окна: достаточно перед удалением проверять ответ пользователя в диалоговом окне следующим образом: if (MessageBox.Show("Are you sure want to delete item?", "Delete confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { modelInstance.Delete(); //execute delete } Более трудоёмкий способ, но с соблюдением всех канонов MVVM: создаёте ViewModel для вашего диалогового окна. Во ViewModel создаёте событие, например: public event EventHandler ConfirmEvent; Событие нужно декорировать специальным аттрибутом, который позволит транслировать его в другие ViewModel-классы, не нарушая при этом принцип high-cohesion loose-coupling. Для этого используются мессенджеры. Можете попробовать Appcelerate.EventBroker. В своих проектах я использую именно его. Далее - создаёте команду, которая ссылается на метод, вызывающий вышеупомянутое событие. Привязываете команду к кнопке в вашем диалоговом окне. private ICommand confirmCommand; public ICommand ConfirmCommand { get { if(confirmCommand==null) { confirmCommand = new Command(p => FireConfirmEvent(), p => ConfirmEventPredicate()); } return confirmCommand; } } В самом окне при помощи метода, декорированного аттрибутом из того же мессенджера обрабатываете это событие. Метод будет содержать код, выполняющий удаление. View в этом случае создавайте, как пару Window.xaml + Window.cs, у которого есть метод ShowDialog(), что автоматически заблокирует вызывающее окно на время открытия диалогового. PS: первый способ не совсем правильный, потому что будет сложно тестировать результат, выбранный пользователем в MessageBox. Добавлено Если захотите использовать это окно в разных местах вашего приложения, создайте базовый абстрактный класс, а в унаследованных VM-классах перегрузите нужные вам свойства. Например, в некоторых случаях вам может понадобиться «дернуть» несколько событий, чтобы на подтверждение среагировало несколько ViewModel. Тут всё зависит от сложности проекта.

Ответ 2



Может быть так: Делаешь окошко с двумя кнопками и со статическим методом Create: public partial class XDialogOkCancel : Window { public static Boolean CreateXDialogOkCancel() { var wnd = new XDialogOkCancel(); if (wnd.ShowDialog().GetValueOrDefault()) return true; else return false; } private XDialogOkCancel() { InitializeComponent(); } private void buttonOk_onClick(object sender, RoutedEventArgs e) { this.DialogResult = true; } private void buttonCancel_onClick(object sender, RoutedEventArgs e) { this.DialogResult = false; //Или поставь IsCansel=true в XAML } } И вызываешь его из своего метода: private void Delete() { if( XDialogOkCancel.CreateXDialogOkCancel()) { //делаю } else { //Не делаю } }

Комментариев нет:

Отправить комментарий