如何在不关闭 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();
            });

        }
    }
}