#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 { //Не делаю } }
Комментариев нет:
Отправить комментарий