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

时间:2014-04-29 11:19:23

标签: c# wpf constructor app-startup

这是我的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在我这样做时会抱怨因为我基本上忽略了第二个构造函数中的参数(我从主屏幕上的按钮启动的那个。我正在尝试有一个统一的构造函数,所以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。
  5. 另外,我在MainWindow上有一个按钮,它必须强制启动Login.xaml但不检查是否有设置。这些是目前独立的构造函数,我想创建它们的1个构造函数。

3 个答案:

答案 0 :(得分:2)

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

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

<Application 
    x:Class="MyNamespace.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources />
</Application>

其中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窗口移至App,仅在需要时显示Login,如果设置实际有效,则仅显示MainWindow。< / p>

答案 1 :(得分:0)

如果要保留它,请尝试使用隐藏而不是关闭

更新: this.Visibility = Visibility.Hidden;

答案 2 :(得分:0)

您需要进行一些调整,然后您可以多次显示多个窗口或单个窗口。

  1. 从App.xaml中删除StartupUri
  2. 为App.xaml设置构建操作为Page
  3. 这将禁用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();
        }
    }