I am building a WPF application using the MVVM Light framework.
I am trying to have a Window open and pass some information, i.e. an object, to this newly created ViewModel.
I have a WPF window (MainListView
/MainListViewModel
) which has a ListBox
bound to a list of objects:
<ListBox ItemsSource="{Binding Selected_Agent.Associated_Letter, Mode=OneWay}"
SelectedItem="{Binding Selected_Letter, Mode=TwoWay}">
<!-- More code below -->
In MainListView
I also have a button bound to a command:
<Button Content="Update" Command="{Binding UpdateCommand}"/>
private ICommand _updateCommand;
public ICommand UpdateCommand
{
get
{
if (_updateCommand == null)
{
_updateCommand = new RelayCommand(_windowService.OpenWindow<AddNewLetterView>, UpdateCommand_CanExecute());
Messenger.Default.Send(new UpdateLetterMessage() { Letter = Selected_Letter });
}
return _updateCommand;
}
}
This opens a new window, AddNewLetterView
using the AddViewLetterViewModel
, which is linked by MVVM Light's ViewModelLocator
.
In AddNewLetterViewModel
constructor I do this:
public AddNewLetterViewModel()
{
Messenger.Default.Register<UpdateLetterMessage>(this, UpdateLetterMessageReceived);
}
The issue is that this message doesn't get received. The breakpoint on UpdateLetterMessageReceived
is never hit, even though the view opens.
If I put a breakpoint on my command it is never hit, and neither is UpdateLetterMessageReceived
on the AddNewLetterViewMdoel
, when the button is clicked, even though the AddNewLetterView
is opened.
What seems to be happening is that UpdateCommand is called once during MainListViewModel instantiation meaning that the Messenge is sent before AddNewLetterViewModel
is instantiated.
Is that correct? If so, how can I make sure that my message is sent when the Command is called?
If not, what is going on here and how can I achieve this?
Your update command needs to be like this:
private ICommand _updateCommand;
public ICommand UpdateCommand
{
get
{
if (_updateCommand == null)
{
_updateCommand = new RelayCommand(() =>
{
_windowService.OpenWindow<AddNewLetterView> ();
Messenger.Default.Send(new UpdateLetterMessage() {Letter = Selected_Letter});
}, UpdateCommand_CanExecute);
}
return _updateCommand;
}
}
The way you had it, it was only sending the message when the command was first created, where I believe you want to send it when the command is executed
By the way I find this structure for commands more helpful. Makes it look like a normal method
public ICommand UpdateCommand => _updateCommand ?? (_updateCommand = new RelayCommand(() =>
{
_windowService.OpenWindow<AddNewLetterView>
Messenger.Default.Send(new UpdateLetterMessage() {Letter = Selected_Letter});
}, UpdateCommand_CanExecute));
To make this clearer, your function was doing this:
private ICommand _updateCommand;
public ICommand UpdateCommand
{
get
{
if (_updateCommand == null)
{
_updateCommand = new RelayCommand(DoSomething, CanDoSomething);
Messenger.Default.Send(etc); <=====THIS SHOULD BE....
}
return _updateCommand;
}
}
public void DoSomething()
{
_windowService etc
<=====.....HERE
}
public bool CanDoSomething() {}
The () => {} notation I've used is a shorthand for defining the function DoSomething