I created a custom confirmation window in an app with Prism Unity, WPF & Mvvm. I need help with the notifications that need to be sent back to the viewmodel. I have this in the detail record view, let's call it MyDetailView.
<!-- Custom Confirmation Window -->
<ie:Interaction.Triggers>
<interactionRequest:InteractionRequestTrigger
SourceObject="{Binding ConfirmationRequest, Mode=TwoWay}">
<mycontrols:PopupWindowAction1 IsModal="True"/>
</interactionRequest:InteractionRequestTrigger>
</ie:Interaction.Triggers>
As shown above, I made the interaction Mode=TwoWay so that the confirmation popup window can send back the button click result for the OK or Cancel button. The confirmation window appears as it should, but I don't know how to send the button click result back to my viewmodel, say MyDetailViewModel. That is the main question.
EDIT: This is MyDetailViewMmodel method that raises the InteractionRequest.
private void RaiseConfirmation()
{ConfirmationRequest
.Raise(new Confirmation()
{
Title = "Confirmation Popup",
Content = "Save Changes?"
}, c =>{if (c.Confirmed)
{ UoW.AdrTypeRos.Submit();}
This is the PopupWindowAction1 class. Part of the answer to the question may be how do I implement the Notification and FinishedInteraction methods.
class PopupWindowAction1 : PopupWindowAction, IInteractionRequestAware
{
protected override Window GetWindow(INotification notification)
{ // custom metrowindow using mahapps
MetroWindow wrapperWindow = new ConfirmWindow1();
wrapperWindow.DataContext = notification;
wrapperWindow.Title = notification.Title;
this.PrepareContentForWindow(notification, wrapperWindow);
return wrapperWindow;
}
public INotification Notification
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public Action FinishInteraction
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
Is there some interaction I need to put in my ConfirmWindow1, something like this?
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonUp">
<ei:CallMethodAction
TargetObject="{Binding RelativeSource={RelativeSource AncestorType=UserControl},
Path=DataContext}"
MethodName="DataContext.ValidateConfirm"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Do I even need to do that type of interaction within the button? If so, how do I code it needs so that it corresponds to the particular viewmodel that invoked the interaction. Any suggestions? Thank you.
Main thing is, when you raise the interaction, provide a callback that is triggered when the interaction is finished. This callback gets the notification back and your interaction should have stored all potentially interesting return values there.
Here's an example...
Relevant parts of the ViewModel:
public InteractionRequest<SelectQuantityNotification> SelectQuantityRequest
{
get;
}
// in some handler that triggers the interaction
SelectQuantityRequest.Raise( new SelectQuantityNotification { Title = "Load how much stuff?", Maximum = maximumQuantity },
notification =>
{
if (notification.Confirmed)
_worldStateService.ExecuteCommand( new LoadCargoCommand( sourceStockpile.Stockpile, cartViewModel.Cart, notification.Quantity ) );
} );
... and from the View:
<i:Interaction.Triggers>
<interactionRequest:InteractionRequestTrigger
SourceObject="{Binding SelectQuantityRequest, Mode=OneWay}">
<framework:FixedSizePopupWindowAction>
<interactionRequest:PopupWindowAction.WindowContent>
<views:SelectSampleDataForImportPopup/>
</interactionRequest:PopupWindowAction.WindowContent>
</framework:FixedSizePopupWindowAction>
</interactionRequest:InteractionRequestTrigger>
</i:Interaction.Triggers>
Additionally, we need a class to hold the data that's passed around, and a ViewModel/View pair for the interaction itself.
Here's the data holding class (note that Maximum
is passed to the interaction, and Quantity
returned from it):
internal class SelectQuantityNotification : Confirmation
{
public int Maximum
{
get;
set;
}
public int Quantity
{
get;
set;
}
}
This is the View of the interaction popup:
<UserControl x:Class="ClientModule.Views.SelectSampleDataForImportPopup"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel Orientation="Vertical">
<TextBlock>
Amount: <Run Text="{Binding Quantity}"/>
</TextBlock>
<Slider Orientation="Horizontal" Minimum="0" Maximum="{Binding Maximum}" Value="{Binding Quantity}" TickPlacement="BottomRight"/>
<Button Content="Ok" Command="{Binding OkCommand}"/>
</StackPanel>
</UserControl>
and it's ViewModel:
internal class SelectSampleDataForImportPopupViewModel : BindableBase, IInteractionRequestAware
{
public SelectSampleDataForImportPopupViewModel()
{
OkCommand = new DelegateCommand( OnOk );
}
public DelegateCommand OkCommand
{
get;
}
public int Quantity
{
get { return _notification?.Quantity ?? 0; }
set
{
if (_notification == null)
return;
_notification.Quantity = value;
OnPropertyChanged( () => Quantity );
}
}
public int Maximum => _notification?.Maximum ?? 0;
#region IInteractionRequestAware
public INotification Notification
{
get { return _notification; }
set
{
SetProperty( ref _notification, value as SelectQuantityNotification );
OnPropertyChanged( () => Maximum );
OnPropertyChanged( () => Quantity );
}
}
public Action FinishInteraction
{
get;
set;
}
#endregion
#region private
private SelectQuantityNotification _notification;
private void OnOk()
{
if (_notification != null)
_notification.Confirmed = true;
FinishInteraction();
}
#endregion
}