In my project I am able to open multiple child windows, display and return information from them, and then close them with a button click. The problem that I am having is that clicking the "Accept" or "Cancel" button closes all open windows. I need to find a way to only close the correct window and I haven't been able to figure out how. I am using MVVM Light and I'm thinking tokens may be the key but I haven't figured out how to make them work. If anybody could help me I'd greatly appreciate it.
Creating the child window in MainWindow:
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var uniqueKey = System.Guid.NewGuid().ToString();
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>(uniqueKey);
adventurerWindowVM.Adv = message.Argument;
var adventurerWindow = new AdventurerView()
{
DataContext = adventurerWindowVM,
Owner = this
};
adventurerWindow.Closed += (sender, args) => SimpleIoc.Default.Unregister(uniqueKey);
adventurerWindow.Show();
});
Sending the close window message from AdventurerViewModel:
private void ExecuteAcceptCommand()
{
Messenger.Default.Send(Adv.Name);
Messenger.Default.Send<CloseWindowMessage>(new CloseWindowMessage());
}
Receiving the close window messsage in AdventurerView:
Messenger.Default.Register<CloseWindowMessage>(this, x => Close());
Token approach:
You have a uniqueKey
you generate each of your AdventurerView
with. Just use that when sending the CloseWindowMessage
as the token.
Firstly in AdventurerViewModel
add a new property of type string say "WindowKey"
public string WindowKey { get; set; }
Next add a constructor to take the unique key in AdventureView
. In AdventurerView.xaml.cs
:
public AdventurerView()
:this(string.Empty) {}
public AdventurerView(string uniqueKey) {
InitializeComponent();
Messenger.Default.Register<CloseWindowMessage>(this, uniqueKey, s => Close());
}
Next in MainWindow.xaml.cs
switch
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var uniqueKey = System.Guid.NewGuid().ToString();
...
adventurerWindow.Show();
});
to
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var uniqueKey = System.Guid.NewGuid().ToString();
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>(uniqueKey);
adventurerWindowVM.Adv = message.Argument;
adventurerWindowVM.WindowKey = uniqueKey;
var adventurerWindow = new AdventurerView(uniqueKey)
{
DataContext = adventurerWindowVM,
Owner = this
};
adventurerWindow.Closed += (sender, args) => SimpleIoc.Default.Unregister<AdventurerViewModel>(uniqueKey);
adventurerWindow.Show();
});
Finally in AdventurerViewModel.xaml.cs
:
switch
private void ExecuteAcceptCommand() {
Messenger.Default.Send(Adv.Name);
Messenger.Default.Send<CloseWindowMessage>(new CloseWindowMessage());
}
to
private void ExecuteAcceptCommand() {
Messenger.Default.Send(Adv.Name);
Messenger.Default.Send<CloseWindowMessage>(new CloseWindowMessage(), WindowKey);
}
Alternate:
Even-though the above would work perfectly fine, there is an alternate to this approach. Your "Message" is already a custom strong type(CloseWindowMessage
). Now you can just add WindowKey
as part of the message and have each Window
when it receives a new CloseWindowMessage
check the WindowKey
in the message against it's own key and Close()
accordingly.