Following question is based on comment in this post: MVVM Understanding Issues
I said that this is codebehind, that does not violate the view and viewmodel separation of concerns:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Closing += MainWindow_Closing;
}
void MainWindow_Closing(object sender, CancelEventArgs e)
{
var canExit = ViewModel.ShowConfirmExitDlg();
if (!canExit) e.Cancel = true;
}
}
The comments was:
Anything in code-behind can't be unit tested, and invoking the creation of a dialog box is logic and therefore shouldn't be in the view
I have two questions:
I could call the viewmodel method from xaml using some EventTriggers and CallMethod actions, but it does not make any difference.
I could do use event aggregator:
public partial class MainWindow : Window
{
private readonly IEventAggregator _eventAggregator;
public MainWindow(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
InitializeComponent();
Closing += MainWindow_Closing;
}
void MainWindow_Closing(object sender, CancelEventArgs e)
{
var evt = new MainWindowClosingEvent();
_eventAggregator.Publish(evt);
e.Cancel = evt.IsCancel;
}
}
and handle the event in viewmodel but does it bring any value? I still cannot unit test cancelling the windows closing event, but I have introduces publishing and subscribing that would be also worth unittestig. It's yet another layer of indirection
Maybe I could route the event to viewmodel:
public MainWindow()
{
InitializeComponent();
Closing += ViewModel.OnWindowClosing;
//or
Closing += (o, e) => ViewModel.OnWindowClosing(e);
}
but I don't see much difference with the original sample.
IMHO, the connection between view and viewmodel cannot be unittested in viewmodel tests, so I either find a way how to test views or it is wild goose chase.
There are two issues here, as I see it. Firstly, you can eliminate some of that code-behind by using the interactivity namespace and commands, for reference look into:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
ICommand goes here - bind to your VM
</i:EventTrigger>
</i:Interaction.Triggers>
when it comes to showing dialogs, you need to consider whether the dialog is view or view-model. When it comes to confirming the window closure, I think of that as purely view. So you can show that inside the code-behind of the Closing event, without IMHO breaking MVVM.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With