如何在IronPython中关闭WPF窗口而不关闭.NET应用程序 [英] How to close WPF window without shutdown .NET Application in IronPython

查看:42
本文介绍了如何在IronPython中关闭WPF窗口而不关闭.NET应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在用IronPython编写WPF应用程序.如果我通过命令"ipy.exe wpf.py"在IronPython REPL之外运行脚本,则一切工作都很好.但是,如果该脚本是通过命令"execfile('wpf.py')"在IronPython REPL中运行的,则该脚本第一次运行正常,而第二次出错:"SystemError:无法创建多个System.Windows.Application实例在同一个AppDomain中."

So I'm writing a WPF application with IronPython. Everything works great if I run the script outside of IronPython REPL via command "ipy.exe wpf.py". 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."

据我了解,这是因为它每次在REPL之外运行时都会创建一个新的AppDomain,而在REPL内运行时它将共享相同的域,并且您可以初始化Application两次.问题是我必须在同一个AppDomain中多次运行它,因为它不是独立的IronPython应用程序.我已经尝试了很多事情,例如通过在app=Application()之后添加app.ShutdownMode = ShutdownMode.OnExplicitShutdown来更改关闭模式,但这只是使整个REPL挂起.

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. The problem is I have to run it inside the same AppDomain many times as it's not a standalone IronPython application. 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.

有人可以帮忙阐明一下吗?非常感谢你!

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

推荐答案

我相信您需要创建一个长期运行的STA线程来承载Applilcation,并通过Applciations的Dispatcher与之通信.这是C#中的示例:

I believe you need to create a long-running STA thread to host the Applilcation, and communicate with it through the Applciations's Dispatcher. Here's an example in 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窗口而不关闭.NET应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆