Tse*_*eng 13
幸运的是,Prism 5.0(我也假设6.0,还没有使用它),有一个类InteractionRequest<T>
,你可以使用代码来提出交互请求.
交互请求基本上是一个窗口,它要求用户执行某个操作,并使用用户决策/操作调用回调(如果必要或需要).
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
}
}
Run Code Online (Sandbox Code Playgroud)
在XAML中你会做类似的事情
<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>
Run Code Online (Sandbox Code Playgroud)
我使用了自己的实现PopupWindowAction
(参见github项目页面的实现)调用LazyPopupWindowAction
,它将实例化嵌入的ConnectionSettingsView
View on click.如果您不关心您的视图只被实例化一次,请随意使用PopupWindowAction
,然后它将与包含该操作的视图同时实例化.
它基本上是复制和粘贴,从我的一个项目切割一些无用的线条.我使用IConfirmation
和INotification
接口而不是具体的实现.
XAML用 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>
Run Code Online (Sandbox Code Playgroud)
命名空间声明
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"
Run Code Online (Sandbox Code Playgroud)
更新:
由于人们不断询问LazyPopupWindowAction
,我将源代码放在GitHub Gist中.基本上它是基于PopupWindowAction
Prims 5(对于Prism来说,尚未用Prism 6进行测试,可能无法正常调整)并完全相同,但也增加了Region和Navigation支持窗口,我在我的应用程序中需要的东西.
我不喜欢默认实现的一件事是,视图和它的viewmodel将在Shell被实例化的同时实例化,并且ViewModel保持在它的状态,当你关闭它时(它实际上只是隐藏).
Hak*_*tık 10
此答案仅适用于 Prism 7,
如果您使用以前版本的 Prism(6 及以下),
则此答案不适合您
Prism 7 彻底改变了打开新窗口的方式。如果您想阅读的话,
这是官方文档。
这里还有一个Youtube 视频,由 Prism 库的创建者解释了这个想法。
Prism 7 推出DialogService
,一种全新的打开新窗口的方式。
<UserControl x:Class="YourUserControlName"
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:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
IDialogAware
接口。public class BaseDialogViewModel : IDialogAware
{
public string Title { get; }
public event Action<IDialogResult> RequestClose;
public virtual void RaiseRequestClose(IDialogResult dialogResult)
{
RequestClose?.Invoke(dialogResult);
}
public virtual bool CanCloseDialog()
{
return true;
}
public virtual void OnDialogClosed()
{
}
public virtual void OnDialogOpened(IDialogParameters parameters)
{
}
}
Run Code Online (Sandbox Code Playgroud)
public void RegisterTypes(IContainerRegistry containerRegistry)
{
// replace 'YourUserControlName' with the class of the view which you created in setp 1
containerRegistry.RegisterDialog<YourUserControlName>();
}
Run Code Online (Sandbox Code Playgroud)
_dialogService.ShowDialog(nameof(YourUserControlName), new DialogParameters(), action);
Run Code Online (Sandbox Code Playgroud)
_dialogService
类型IDialogService
并被注入到视图模型中,您将在其中使用它,例如public MainViewModel(IDialogService dialogService)
{
this._dialogService = dialogService;
}
Run Code Online (Sandbox Code Playgroud)
需要执行前面的所有步骤才能显示该窗口。
如果您需要,还有一些其他可选步骤(非必需)
prism:Dialog.WindowStyle
您可以通过添加以下xaml 元素来指定 Window 的属性
<UserControl x:Class="YourUserControlName"
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:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen" />
<Setter Property="ResizeMode" Value="NoResize"/>
<Setter Property="ShowInTaskbar" Value="False"/>
<Setter Property="WindowState" Value="Maximized"/>
</Style>
</prism:Dialog.WindowStyle>
<Grid>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
public static class DialogServiceExtensions
{
public static void ShowWindowTest(this IDialogService dialogService, Action<IDialogResult> action)
{
dialogService.ShowDialog(nameof(WindowTestView), new DialogParameters(), action);
}
}
Run Code Online (Sandbox Code Playgroud)
Prism 文档建议但不要求这样做。
如果您想要使用 .NET Core 3.1 的新 Prism 7 WPF 应用程序的样板设置,那么您可以查看此Github 存储库
,它包含上述设置以及用于启动 WPF Prism 应用程序的许多其他有用功能。
免责声明:我是存储库的作者
更新
是什么让我得出另一个答案是无法在我使用Prism 6的项目中应用已接受的答案,
但在提出原始答案(见下文)并在评论中讨论之后,我发现核心问题是:该棱镜6改变了一些类的命名空间,这在公认的答案是仍然存在使用的所有类棱镜6,但在另一个DLL和命名空间
因此,如果您使用的棱镜6,你可以申请使用这些修改的接受的答案
首先替换那些名字
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"
Run Code Online (Sandbox Code Playgroud)
具有以下命名空间
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:prism="http://prismlibrary.com/"
Run Code Online (Sandbox Code Playgroud)
第二次更新XAML如下
<Button Content="Options" Command="{Binding OpenConnectionOptionsCommand}">
<i:Interaction.Triggers>
<prism:InteractionRequestTrigger SourceObject="{Binding OptionSettingConfirmationRequest, Mode=OneWay}" >
<prism:PopupWindowAction>
<prism:PopupWindowAction.WindowContent>
<views:CustomPopupView />
</prism:PopupWindowAction.WindowContent>
</prism:PopupWindowAction>
</prism:InteractionRequestTrigger>
</i:Interaction.Triggers>
</Button>
Run Code Online (Sandbox Code Playgroud)
注意1
确保您使用的视图(在上面的示例中<views:CustomPopupWindow>
)不是窗口,否则您将收到异常.
注2: 只有在使用Prism 6时才
需要进行这些修改.因为(正如我在下面的原始答案中所说),Prism 6中不推荐接受答案使用的dll .
注3
:确保引用Prism.Wpf
dll,可以从Nuget下载.
实际上你在你的问题中引用的文章非常有用(至少对我而言),并且它不会崩溃.
我会尝试总结那篇文章.
视图模型
public class ViewModel : BindableBase
{
public ViewModel()
{
_showWindowCommand = new DelegateCommand(ShowWindow);
_interactionRequest = new InteractionRequest<Confirmation>();
}
private readonly DelegateCommand _showWindowCommand;
private InteractionRequest<Confirmation> _interactionRequest;
public ICommand ShowWindowCommand
{
get { return _showWindowCommand; }
}
public IInteractionRequest InteractionRequest
{
get { return _interactionRequest; }
}
private void ShowWindow()
{
_interactionRequest.Raise(
new Confirmation(),
OnWindowClosed);
}
private void OnWindowClosed(Confirmation confirmation)
{
if (confirmation.Confirmed)
{
//perform the confirmed action...
}
else
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
XAML
<Button Command="{Binding ShowWindowCommand}" Content="Show Window" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Raised" SourceObject="{Binding InteractionRequest}">
<i:EventTrigger.Actions>
<local:ShowWindowAction></local:ShowWindowAction>
</i:EventTrigger.Actions>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Run Code Online (Sandbox Code Playgroud)
并且您将需要使用这些名称空间
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:The namespace which contains the ShowWindowAction">
Run Code Online (Sandbox Code Playgroud)
ActionTrigger
using System;
using Prism.Interactivity.InteractionRequest;
using System.Windows.Interactivity;
using System.Windows;
public class ShowWindowAction : TriggerAction<FrameworkElement>
{
protected override void Invoke(object parameter)
{
InteractionRequestedEventArgs args = parameter as InteractionRequestedEventArgs;
if (args != null)
{
Confirmation confirmation = args.Context as Confirmation;
if (confirmation != null)
{
// Replace ParametersWindow with your own window.
ParametersWindow window = new ParametersWindow();
EventHandler closeHandler = null;
closeHandler = (sender, e) =>
{
window.Closed -= closeHandler;
args.Callback();
};
window.Closed += closeHandler;
window.Show();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
说明
Prism.Core
和Prism.Wpf
dll(至少)使这段代码有效.ShowWindow
方法,将触发Invoke
方法ShowWindowAction
,这将真正显示窗口.OnWindowClosed
,我们将它作为回调传递给ShowWindowAction
类,当窗口真正关闭时我们从那里调用它. 归档时间: |
|
查看次数: |
10511 次 |
最近记录: |