关闭窗口后,无法设置可见性或调用Show、ShowDialog或EnsureHandle
本文关键字:调用 Show EnsureHandle ShowDialog 可见性 设置 窗口 | 更新日期: 2023-09-27 18:00:48
这是我的WPF应用程序的应用程序构造函数:
public partial class App
{
public App()
{
Run(new Login(false));
}
}
这是我的登录构造函数:
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();
}
}
它启动应用程序构造函数并顺利通过登录构造函数,但一旦在完成登录构造函数后再次到达应用程序构造函数,它就会崩溃,并出现InvalidOperationException,并附带附加信息:"在窗口关闭后,无法设置可见性或调用Show、ShowDialog或WindowInteropHelper.EnsureHandle。">
构造函数的目标如下:当应用程序第一次启动时,我想检查这个应用程序是否有现有的设置。如果它们存在,我想使用这些设置连接到第三方(Dynamics CRM 2011(,打开主应用程序窗口,然后关闭登录屏幕。如果它们不在那里,我希望用户设置设置。
然而,我也希望能够从主屏幕上的按钮启动这个窗口,在这种情况下,它应该忽略默认设置,并再次启动登录窗口,允许我再次设置设置。
我已经设法使用2个构造函数使其工作,但当我这样做时,Resharper会抱怨,因为我基本上忽略了第二个构造函数中的参数(我从主屏幕上的按钮启动的那个构造函数(。我试图有一个统一的构造函数,所以Resharper不会抱怨。这可能吗?
编辑:我不想保留我的登录窗口,因为我在更改设置时会创建一个新窗口,在我的主窗口中使用以下代码:
private void BtnSettings_Click(object sender, RoutedEventArgs e)
{
Login login = new Login(true);
login.Show();
Close();
}
编辑:一些澄清:我不想显示多个窗口。我想要的是:
- 启动时,启动Login.xaml
- 当Login.xaml启动时,检查是否已经设置了设置
- 如果没有设置,显示Login.Xaml进行设置
- 如果设置了"设置",则使用保存的设置启动MainWindow
此外,我在MainWindow上有一个按钮,它必须强制启动Login.xaml,但不检查是否有设置。这些是目前独立的构造函数,我想为它们创建一个构造函数。
您的更新使您更清楚地了解想要实现的目标。我建议重新构造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>
其中MyNamespace
是App
类的名称空间。
现在您要从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
。
您需要进行一些调整,然后可以多次显示多个窗口或单个窗口。
- 从App.xaml中删除
StartupUri
- 将App.xaml的Build操作设置为
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
更新:这Visibility=Visibility.Hiddden;
我也面临着类似的挑战,确保在加载窗口后调用任何可能关闭正在打开的窗口的函数。
对于您正在打开的窗口,请在xaml文件中设置
Loaded="Window_Loaded"
然后在cs文件中,
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//call your function here
}
这解决了我的问题,希望这能帮助