如何在不关闭 IronPython 中的 .NET 应用程序的情况下关闭 WPF window
How to close WPF window without shutdown .NET Application in IronPython
所以我正在用 IronPython 编写一个 WPF 应用程序。如果我 运行 通过命令 "ipy.exe wpf.py" 在 IronPython REPL 之外的脚本,一切都很好。但是,如果脚本通过命令 "execfile('wpf.py')" 在 IronPython REPL 中 运行,第一次它 运行 OK,第二次它出错 "SystemError: Cannot create more than one System.Windows.Application instance in the same AppDomain."
根据我的理解,这是因为每次在 REPL 之外 运行 它都会创建一个新的 AppDomain,而在 REPL 内部 运行ning 时它会共享同一个域,你可以初始化 Application
两次。问题是我必须在同一个 AppDomain 中多次 运行 它,因为它不是独立的 IronPython 应用程序。我已经尝试了很多事情,例如通过在 app=Application()
之后添加 app.ShutdownMode = ShutdownMode.OnExplicitShutdown
来更改关闭模式,但这只会挂起整个 REPL。
有人可以帮忙解释一下吗?非常感谢!
import clr
clr.AddReference("PresentationFramework")
clr.AddReference("PresentationCore")
clr.AddReference("System.Xml")
from System.Xml import XmlReader
from System.IO import StringReader
from System.Windows.Markup import XamlReader
from System.Windows import Application
s = XmlReader.Create(StringReader('''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="IronPython MVVM Demo2"
Width="450"
SizeToContent="Height">
<Grid Margin="15" x:Name="grid1">
<StackPanel Margin="5">
<Button Margin="5">One</Button>
<Button Margin="5">Two</Button>
<Button Margin="5">Three</Button>
</StackPanel>
</Grid>
</Window>
'''))
win = XamlReader.Load(s)
app = Application()
app.Run(win)
print("The End.")
我认为您需要创建一个长 运行 STA 线程来托管 Applilcation,并通过 Applciations 的 Dispatcher 与其通信。这是 C# 中的示例:
using System;
using System.IO;
using System.Threading;
using System.Windows;
using System.Xml;
namespace ConsoleApp1
{
class Program
{
static void ShowWindow(string Xaml)
{
var s = XmlReader.Create(new StringReader(Xaml));
var win = (Window)System.Windows.Markup.XamlReader.Load(s);
win.ShowDialog();
}
static void Main(string[] args)
{
Application app = null;
var UIThread = new Thread(() =>
{
app = new Application();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
});
UIThread.SetApartmentState(ApartmentState.STA);
UIThread.Start();
while (app == null )
Thread.Sleep(100);
app.Dispatcher.Invoke(() => Console.WriteLine("Started"));
var xaml = @"
<Window
xmlns = ""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x = ""http://schemas.microsoft.com/winfx/2006/xaml""
Title = ""IronPython MVVM Demo2""
Width = ""450""
SizeToContent = ""Height"">
<Grid Margin = ""15"" x:Name = ""grid1"">
<StackPanel Margin = ""5"">
<Button Margin = ""5""> One </Button>
<Button Margin = ""5""> Two </Button>
<Button Margin = ""5""> Three </Button>
</StackPanel>
</Grid>
</Window>";
for (int i = 0; i < 3; i++)
{
Application.Current.Dispatcher.Invoke(() =>
{
ShowWindow(xaml);
});
}
Application.Current.Dispatcher.Invoke(() =>
{
Application.Current.Shutdown();
});
}
}
}
所以我正在用 IronPython 编写一个 WPF 应用程序。如果我 运行 通过命令 "ipy.exe wpf.py" 在 IronPython REPL 之外的脚本,一切都很好。但是,如果脚本通过命令 "execfile('wpf.py')" 在 IronPython REPL 中 运行,第一次它 运行 OK,第二次它出错 "SystemError: Cannot create more than one System.Windows.Application instance in the same AppDomain."
根据我的理解,这是因为每次在 REPL 之外 运行 它都会创建一个新的 AppDomain,而在 REPL 内部 运行ning 时它会共享同一个域,你可以初始化 Application
两次。问题是我必须在同一个 AppDomain 中多次 运行 它,因为它不是独立的 IronPython 应用程序。我已经尝试了很多事情,例如通过在 app=Application()
之后添加 app.ShutdownMode = ShutdownMode.OnExplicitShutdown
来更改关闭模式,但这只会挂起整个 REPL。
有人可以帮忙解释一下吗?非常感谢!
import clr
clr.AddReference("PresentationFramework")
clr.AddReference("PresentationCore")
clr.AddReference("System.Xml")
from System.Xml import XmlReader
from System.IO import StringReader
from System.Windows.Markup import XamlReader
from System.Windows import Application
s = XmlReader.Create(StringReader('''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="IronPython MVVM Demo2"
Width="450"
SizeToContent="Height">
<Grid Margin="15" x:Name="grid1">
<StackPanel Margin="5">
<Button Margin="5">One</Button>
<Button Margin="5">Two</Button>
<Button Margin="5">Three</Button>
</StackPanel>
</Grid>
</Window>
'''))
win = XamlReader.Load(s)
app = Application()
app.Run(win)
print("The End.")
我认为您需要创建一个长 运行 STA 线程来托管 Applilcation,并通过 Applciations 的 Dispatcher 与其通信。这是 C# 中的示例:
using System;
using System.IO;
using System.Threading;
using System.Windows;
using System.Xml;
namespace ConsoleApp1
{
class Program
{
static void ShowWindow(string Xaml)
{
var s = XmlReader.Create(new StringReader(Xaml));
var win = (Window)System.Windows.Markup.XamlReader.Load(s);
win.ShowDialog();
}
static void Main(string[] args)
{
Application app = null;
var UIThread = new Thread(() =>
{
app = new Application();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
});
UIThread.SetApartmentState(ApartmentState.STA);
UIThread.Start();
while (app == null )
Thread.Sleep(100);
app.Dispatcher.Invoke(() => Console.WriteLine("Started"));
var xaml = @"
<Window
xmlns = ""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x = ""http://schemas.microsoft.com/winfx/2006/xaml""
Title = ""IronPython MVVM Demo2""
Width = ""450""
SizeToContent = ""Height"">
<Grid Margin = ""15"" x:Name = ""grid1"">
<StackPanel Margin = ""5"">
<Button Margin = ""5""> One </Button>
<Button Margin = ""5""> Two </Button>
<Button Margin = ""5""> Three </Button>
</StackPanel>
</Grid>
</Window>";
for (int i = 0; i < 3; i++)
{
Application.Current.Dispatcher.Invoke(() =>
{
ShowWindow(xaml);
});
}
Application.Current.Dispatcher.Invoke(() =>
{
Application.Current.Shutdown();
});
}
}
}