我是WPF / Prism的新手,我尝试执行以下操作:我需要在启动主窗口之前加载登录视图(窗口或用户控件)。成功登录后,删除“登录”视图并转到主界面。
我在这里查看了几个答案,但是所有答案都使用boostrapper类引用了PRISM的较早版本。
我有一个WPF(Prism 7)应用程序,其中包含主项目和一个授权模块。
从我的主项目App.xaml.cs
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<AuthorizationModule>();
}
在“授权”模块中,我有我的LoginView / LoginViewModel。授权模块注册一个LoginService,它将注入到LoginViewModel
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register(typeof(ILoginService), typeof(LoginService));
}
LoginViewModel将负责使用此LoginService对用户进行身份验证。
我看到的部分答案显示如下:
protected override void InitializeShell()
{
Window login = new LoginView();
var loginVM = new LoginViewModel(new LoginAuth());
loginVM.LoginCompleted += (sender, args) =>
{
login.Close();
Application.Current.MainWindow.Show();
};
login.DataContext = loginVM;
// problem below:
login.ShowDialog();
}
但是,这似乎有点麻烦,不必手动实例化LoginView,而不仅仅是让容器为您完成。
此外,PRISM 7上的InitiallizeShell期望当前正在创建的Shell。我不确定是否应该使用传递给激活主窗口的值。
protected override void InitializeShell(Window shell)
我还从Github上的Brian Lagunas身上读到了也许使用EventAggregator(我已经尝试过)的信息。我已经通过授权模块注册了EventAggregator,并从LoginViewModel中成功登录后发布了SuccessLoginEvent,但是我可以弄清楚如何从Main app订阅该事件
因此,基本上预期的结果是,在应用程序启动时,如果用户未登录,则显示LoginView,在用户对其自身进行身份验证之后,将他带到已经加载了所有所需模块的MainWindow中。
任何帮助将不胜感激。
答案 0 :(得分:0)
我尝试了一下,并提出了以下建议:
应用程序:
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<Login>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register(typeof(object), typeof(Login), "Login");
containerRegistry.RegisterInstance(typeof(LoginViewModel), new LoginViewModel(Container.GetContainer(), Container.Resolve<RegionManager>()));
containerRegistry.Register(typeof(object), typeof(MainWindow), "MainWindow");
containerRegistry.RegisterInstance(typeof(MainWindowViewModel), new MainWindowViewModel(Container.GetContainer(), Container.Resolve<RegionManager>()));
}
}
XAML:
<Window x:Class="LoginTest.Views.Login"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:LoginTest.Views"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="Login" Height="250" Width="400">
<Grid>
<Button Content="Login" HorizontalAlignment="Left" Height="61" Margin="100,100,0,0" VerticalAlignment="Top" Width="164" Command="{Binding LoginCommand}"/>
</Grid>
隐藏代码:
public partial class Login : Window
{
public Login()
{
InitializeComponent();
((LoginViewModel)DataContext).NewWindow += StartMainApp;
((LoginViewModel)DataContext).CloseWindow += CloseWindow;
}
private void StartMainApp(Object win)
{
Application.Current.MainWindow = (Window)win;
Application.Current.MainWindow.Show();
}
private void CloseWindow()
{
this.Close();
}
}
ViewModel:
class LoginViewModel : BindableBase
{
private readonly IUnityContainer _container;
private readonly IRegionManager _regionManager;
private PrismApplication _application;
private string _title = "Prism Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public DelegateCommand LoginCommand { get; set; }
public delegate void NewWindowDelegate(Object win);
public delegate void CloseWindowDelegate();
public CloseWindowDelegate CloseWindow{ get; set; }
public NewWindowDelegate NewWindow { get; set; }
public LoginViewModel(IUnityContainer container, IRegionManager regionManager)
{
_regionManager = regionManager;
_container = container;
LoginCommand = new DelegateCommand(OnLogin);
}
private void OnLogin()
{
Trace.WriteLine("Logging in");
// do your login stuff
// If Login OK continue here
NewWindow.Invoke(_container.Resolve<MainWindow>());
CloseWindow.Invoke();
}
}
我希望我的例子有用!
答案 1 :(得分:0)
我要感谢user947737的良好建议。我自己尝试过,对我来说很有效。 另外,当然,我添加了MainWindowsModelView构造函数。
public class MainWindowViewModel : BindableBase
{
private readonly IUnityContainer _container;
private readonly IRegionManager _regionManager;
private PrismApplication _application;
//private string _title = "Prism Application";
//public string Title
//{
// get { return _title; }
// set { SetProperty(ref _title, value); }
//}
public MainWindowViewModel(IUnityContainer container, IRegionManager regionManager)
{
_container = container;
_regionManager = regionManager;
}
}