Luckily, Prism 5.0 (and I assume 6.0 too, haven't worked with it yet), has a class called InteractionRequest<T>
which you can use from code to raise interaction requests.
An interaction request is basically a window, that asks the user for a certain action and calls a callback (if necessary or desired) with the users decisions/actions.
public class ShellViewModel : BindableBase
{
private readonly IRegionManager regionManager;
public ShellViewModel(IRegionManager regionManager)
{
if (regionManager == null)
throw new ArgumentNullException("regionManager");
this.regionManager = regionManager;
this.OptionSettingConfirmationRequest = new InteractionRequest<IConfirmation>();
openConnectionOptionsCommand = new DelegateCommand(RaiseConnectionOptionsRequest);
}
public InteractionRequest<IConfirmation> OptionSettingConfirmationRequest { get; private set; }
private readonly ICommand openConnectionOptionsCommand;
public ICommand OpenConnectionOptionsCommand { get { return openConnectionOptionsCommand; } }
private void RaiseConnectionOptionsRequest()
{
this.OptionSettingConfirmationRequest.Raise(new Confirmation { Title = "Options not saved. Do you wish to save?" }, OnConnectionOptionsResponse);
}
protected virtual void OnConnectionOptionsResponse(IConfirmation context)
{
if(context.Confirmed)
{
// save it
}
// otherwise do nothing
}
}
In XAML you would do something like
<Button Content="Options" Command="{Binding OpenConnectionOptionsCommand}">
<i:Interaction.Triggers>
<pit:InteractionRequestTrigger SourceObject="{Binding OptionSettingConfirmationRequest, Mode=OneWay}" >
<pie:LazyPopupWindowAction RegionName="ConnectionSettings"
NavigationUri="ConnectionSettingsView" IsModal="True" />
</pit:InteractionRequestTrigger>
</i:Interaction.Triggers>
</Button>
I used my own implemetation of PopupWindowAction
(see github project page for it's implementation) called LazyPopupWindowAction
, which will instantiate the embedded ConnectionSettingsView
View on click. If you don't care that your view is instantiated only once, feel free to use PopupWindowAction
, then it will be instantiated at the same time as the View containing the action.
It's basically copy & paste with cutting some useless lines from one of my projects. I used IConfirmation
and INotification
interfaces instead of the concrete implementations.
XAML with PopupWindowAction
<Button Content="Options" Command="{Binding OpenConnectionOptionsCommand}">
<i:Interaction.Triggers>
<pit:InteractionRequestTrigger SourceObject="{Binding OptionSettingConfirmationRequest, Mode=OneWay}" >
<pi:PopupWindowAction>
<pi:PopupWindowAction.WindowContent>
<views:CustomPopupView />
</pi:PopupWindowAction.WindowContent>
</pi:PopupWindowAction>
</pit:InteractionRequestTrigger>
</i:Interaction.Triggers>
</Button>
Namespace declarations
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:pi="clr-namespace:Microsoft.Practices.Prism.Interactivity;assembly=Microsoft.Practices.Prism.Interactivity"
xmlns:pit="clr-namespace:Microsoft.Practices.Prism.Interactivity.InteractionRequest;assembly=Microsoft.Practices.Prism.Interactivity"
xmlns:pie="clr-namespace:MyProject.UI.Prism.Interactivity;assembly=MyProject.UI"
Update:
Since people keep asking about the LazyPopupWindowAction
, I've put the source in a GitHub Gist. Basically it's based on the PopupWindowAction
from Prims 5 (and for Prism, haven't test it with Prism 6 yet, probably won't work w/o adjustments) and does the exact same thing, but also adds Region and Navigation support with the opened window, something that I needed in my application.
One thing I disliked about the default implementation was, that the view and it's viewmodel will be instantiated at the same time the Shell gets instantiated and the ViewModel remains in it's state, when you close it (it was actually just hidden).