窗口关闭后,无法设置可见性或调用Show,ShowDialog或EnsureHandle

这是我的WPF应用程序的App构造函数:

public partial class App { public App() { Run(new Login(false)); } } 

这是我的Login构造函数:

 public Login(bool ignoreSettings) { InitializeComponent(); if (ignoreSettings) { TxtUsername.Text = SettingsSaver.LoadUsername(); TxtCrmUrl.Text = SettingsSaver.LoadCrmUrl(); return; } if (string.IsNullOrWhiteSpace(SettingsSaver.LoadUsername()) || string.IsNullOrWhiteSpace(SettingsSaver.LoadCrmUrl())) return; try { CrmConnector.ConnectToCrm(); MainWindow mainWindow = new MainWindow(); mainWindow.Show(); } catch (SecurityAccessDeniedException) { MessageBox.Show(@"Uw inloggegevens zijn niet correct. Gelieve deze te controleren en opnieuw te proberen."); } finally { Close(); } } 

它启动App构造函数并完成Login构造函数,但是一旦它在完成Login构造函数后再次到达App Constructor,它就会发生InvalidOperationException崩溃,并附带以下信息:“无法设置可见性或调用Show,ShowDialog或WindowInteropHelper窗口关闭后.EnsureHandle。

构造函数的目标如下:首次启动应用程序时,我想检查此应用程序是否存在现有设置。 如果它们存在,我想使用这些设置连接到第三方(Dynamics CRM 2011),打开主应用程序窗口,然后关闭登录屏幕。 如果它们不存在,我希望用户设置设置。

但是,我还希望能够从主屏幕上的按钮启动此窗口,在这种情况下,它应该忽略默认设置并再次启动登录窗口,允许我再次设置设置。

我已经设法使用2个构造函数让它工作,但Resharper在我这样做时会抱怨因为我基本上忽略了第二个构造函数中的参数(我从主屏幕上的按钮启动的那个。我正试图拥有1个统一的构造函数让Resharper不抱怨。这可能吗?

编辑:我不想保留我的登录窗口,因为我在更改设置时创建了一个新窗口,使用我的MainWindow中的以下代码:

 private void BtnSettings_Click(object sender, RoutedEventArgs e) { Login login = new Login(true); login.Show(); Close(); } 

编辑:一些澄清:我不想显示多个窗口。 我想要的是:

  1. 在启动时,启动Login.xaml;
  2. 启动Login.xaml时,检查设置是否已设置;
  3. 如果没有设置,请显示Login.Xaml进行设置;
  4. 如果设置了设置,请使用保存的设置启动MainWindow。

另外,我在MainWindow上有一个按钮,它必须强制启动Login.xaml但不检查是否有设置。 这些是目前单独的构造函数,我想制作它们的1个构造函数。

您的更新使您想要实现的目标更加清晰。 我建议重新构建Login窗口以使其更具单一责任,并将validation逻辑推送到App类中,以便它负责管理初始化流程。 配方如下:

改变App.Xaml.cs ,使它看起来像这样; 重要的是没有StartupUri

    

其中MyNamespaceApp类的命名空间。

现在,您将从App.OnStartup手动启动应用程序

 public partial class App { protected override void OnStartup(System.Windows.StartupEventArgs e) { base.OnStartup(e); if (!AreSettingsSet()) { this.MainWindow = new Login(); this.MainWindow.ShowDialog(); // Waits until closed. // Recheck the settings now that the login screen has been closed. if (!AreSettingsSet()) { // Tell the user there is a problem and quit. this.Shutdown(); } } this.MainWindow = new MainWindow(); this.MainWindow.Show(); } private bool AreSettingsSet() { // Whatever you need to do to decide if the settings are set. } } 

总结一下:从Login窗口删除validation逻辑到App ,只在需要时显示Login如果设置实际有效,则只显示MainWindow

你需要做一些调整,然后你可以多次显示几个窗口或单个窗口。

  1. 从App.xaml中删除StartupUri
  2. 将Build操作设置为App.xaml的Page

这将禁用App.g.ics的自动生成,您可以创建自己的应用程序入口点:

 public partial class App : Application { [STAThread] public static void Main() { App app = new App(); app.InitializeComponent(); app.ShowWindow1(); app.ShowWindow1(); // show second time same window (new instance) } public void ShowWindow1() { // show window1 in separate method, so that instance will be deleted after method ends Window1 window1 = new Window1(); // optional (as it seems) // MainWindow = window1 widow1.Show(); } } 

如果你想保留它,请尝试使用Visibility.Hidden而不是Close

更新:this.Visibility = Visibility.Hidden;

Interesting Posts