简体   繁体   English

如何在不关闭 IronPython 中的 .NET 应用程序的情况下关闭 WPF 窗口

[英]How to close WPF window without shutdown .NET Application in IronPython

So I'm writing a WPF application with IronPython.所以我正在用 IronPython 编写一个 WPF 应用程序。 Everything works great if I run the script outside of IronPython REPL via command "ipy.exe wpf.py".如果我通过命令“ipy.exe wpf.py”在 IronPython REPL 之外运行脚本,一切都会很好。 However, if the script were run inside IronPython REPL via command "execfile('wpf.py')", the first time it runs OK, the second time it errors out "SystemError: Cannot create more than one System.Windows.Application instance in the same AppDomain."但是,如果脚本是通过命令“execfile('wpf.py')”在 IronPython REPL 中运行的,第一次运行正常,第二次它会出错“SystemError:无法创建多个 System.Windows.Application 实例在同一个 AppDomain 中。”

From my understanding, it's because it'll create a new AppDomain every time you run it outside REPL while it'll share the same domain when running inside REPL, and you can initialize Application twice.根据我的理解,这是因为它每次在 REPL 外运行时都会创建一个新的 AppDomain,而在 REPL 内运行时它将共享相同的域,并且您可以两次初始化Application The problem is I have to run it inside the same AppDomain many times as it's not a standalone IronPython application.问题是我必须在同一个 AppDomain 中多次运行它,因为它不是独立的 IronPython 应用程序。 I've tried many things such as change shutdown mode by add app.ShutdownMode = ShutdownMode.OnExplicitShutdown after app=Application() , but that just hang the whole REPL.我已经尝试了很多事情,例如通过在app=Application()之后添加app.ShutdownMode = ShutdownMode.OnExplicitShutdown来更改关闭模式,但这只会挂起整个 REPL。

Can someone please help shed some light?有人可以帮忙解释一下吗? Thank you very much!非常感谢!

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.")   

I believe you need to create a long-running STA thread to host the Applilcation, and communicate with it through the Applciations's Dispatcher.我相信您需要创建一个长时间运行的 STA 线程来托管 Application,并通过 Applciations 的 Dispatcher 与其进行通信。 Here's an example in C#:这是 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();
            });

        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM