I have an AddClientViewModel which is referenced by 2 views (AddClientView and SuggestedAddressesView). The AddClientView is a form which has a field for an address. The form has a validate button which validates the entered address using Geocoding. If more than one address is returned, the SuggestedAddressesView opens.
Here is how I am currently doing it:
AddClientViewModel:
private void ValidateExecute(object obj)
{
SuggestedAddresses = new ObservableCollection<DBHelper.GeocodeService.GeocodeResult>(GeoCodeTest.SuggestedAddress(FormattedAddress));
....
if (SuggestedAddresses.Count > 0)
{
var window = new SuggestedAddressesView(this);
window.DataContext = this;
window.Show();
}
}
Here is the SuggestedAddressesView constructor where AddClientViewModel inherits from ViewModelBase
public SuggestedAddressesView(ViewModelBase viewModel)
{
InitializeComponent();
viewModel.ClosingRequest += (sender, e) => this.Close();
}
The other problem I am having is when I call OnClosingRequest() from the AddClientViewModel...both the AddClientView and SuggestedAddressesView closes. I know this happens because both views reference the same ViewModel. This is not the behaviour I want. I would like to be able to independently close either Window.
Is opening a View from the ViewModel proper MVVM structure and how would I go about being able to close windows independently?
While a view should only have one viewmodel, a single viewmodel might be used by multiple views (imagine a wizard, for example, that has three views but all bind to the same viewmodel that drives the process).
This can be done directly in xaml (the View just instances the ViewModel directly). This can be done in the View's constructor ( this. DataContext = new MyViewModel(); )
As soon as you refer to UI elements(In this case the View) from the VM, you're going against suggested MVVM Guidelines. With just that we can know creating the Window
object in the VM is wrong.
So now onto rectifying this:
AddClientView
and SuggestedAddressesView
with their own VM. Great!Implementing a View Open/Close from the VM:
Messenger
(MVVM Light), EventAggregator
(PRISM) and so on to send a "message" from the VM to the View when you need to open/close a View and do the actual operation in the View. Using a "Messenger" approach to handle View open:
AddClientViewModel
which would have to ask for the SuggestedAddressesView
to be opened.SuggestedAddresses.Count > 0
, you would send a message to the AddClientView
asking it to open up the SuggestedAddressesView
.AddClientView.xaml.cs
upon receiving this message, you would do what you're currently doing in the VM. Create an object of SuggestedAddressesView
and call .Show()
on it.DataContext
of SuggestedAddressesView
as SuggestedAddressesViewModel
.That's it. Now what you have is, when AddClientViewModel
wants SuggestedAddressesView
shown, it sends a message to it's own View and the View in-turn creates and shows the SuggestedAddressesView
. This way the VM does not reference any View's and we keep to holding MVVM standards.
Using a "Messenger" approach to handle View close:
View
is pretty simple. Again when you need to close the View from the VM, you send a message to it's own View asking for it to be closed..Hide()
/ .Close()
or however else you want to get rid of it.In this each VM handles it's own View's closing and you don't have any inter-connected dependencies.
You can use this as a start point to guide you in handling "messages" for this approach. it has an attached download you can get and see how the Messenger
works. This is with MVVM Light, if you do not use it or use something else/ your own MVVM implementation, use it as a guide to help get to what you need.
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