简体   繁体   English

使用ShowDialog()从STA线程显示窗口

[英]Displaying Window from STA Thread using ShowDialog()

I need to open a window from a dll project (Runs in the background or is triggered when called). 我需要从dll项目中打开一个窗口(在后台运行或在调用时触发)。 For this to be possible I need to open a window from a method marked as [STAThread] to create an instance of the window. 为此,我需要使用标记为[STAThread]的方法打开一个窗口以创建该窗口的实例。

I am using the MVVM pattern to bind the ViewModel to a View, and the view is added to the MainWindow as a usercontrol. 我正在使用MVVM模式将ViewModel绑定到视图,并且该视图作为用户控件添加到MainWindow。

On the View there is a button bound to a command that 'closes' the window. 在“视图”上,有一个按钮绑定到“关闭”窗口的命令。 The command in the ViewModel calls the CloseCommand(), which in turn will call the window.Close() method. ViewModel中的命令调用CloseCommand(),后者又将调用window.Close()方法。

Code Snippet: 代码段:

    MethodShowingTheWindow() {
        var idVM = new IDWindowViewModel();
        ShowForm<MainWindow>(idVM); // Works fine, Close Command closes the window.
        ShowForm<MainWindow>(idVM); // hits the ShowDialog() line, then just jumps to the while loop 
        ShowForm<MainWindow>(idVM);        // waiting for the thread to finish. Never displays the window.
        ShowForm<MainWindow>(idVM);

    }

    [STAThread]
    public void ShowForm<T>(IViewModel vm) {
        Thread th = new Thread(new ThreadStart(delegate {
            var window = new MainWindow();
            window.DataContext = vm;

            vm.CloseAction = new Action(() => window.Close()); // Does this when the Close Action is called from the viewmodel (Close the window).

            try {
                window.ShowDialog();
            } catch (Exception ex) {
                throw ex;
            }
        }));

        th.ApartmentState = ApartmentState.STA;
        th.Start();

        while (th.IsAlive) {
            //Wait for thread to finish
        }
    }

All I need to know is why the window wont appear with the second ShowWindow(idVM) call? 我只需要知道为什么窗口不会在第二次ShowWindow(idVM)调用中出现? All I can think of is that the Window is not correctly closed/Disposed. 我能想到的是,窗口没有正确关闭/处理。 I tried adding the following to the CloseAction Action: 我尝试将以下内容添加到CloseAction操作中:

...
vm.CloseAction = new Action(() => {
    if (window is IDisposable) (window as IDisposable).Dispose();
    window.Close();
});

but (window is IDisposable) == false? 但是(窗口是IDisposable)==假?

Any help would be greatly appreciated. 任何帮助将不胜感激。

This is my implementation for your scenario. 这是我为您设计的方案。 Using Dispatcher in order to avoid STA Exceptions: 使用分派器以避免STA异常:

async Task MethodShowingTheWindow() 
{
    var idVM = new IDWindowViewModel();
    await ShowForm<MainWindow>(idVM); // Works fine, Close Command closes the window.
    await ShowForm<MainWindow>(idVM); // hits the ShowDialog() line, then just jumps to the while loop 
    await ShowForm<MainWindow>(idVM);        // waiting for the thread to finish. Never displays the window.
    await ShowForm<MainWindow>(idVM);
}

public await Task ShowForm<T>(IViewModel vm) 
{
    Dispatcher.InvokeAsync(() =>
    {
        var window = new MainWindow();
        window.DataContext = vm;
        System.Windows.Application.Current.Dispatcher.Invoke(() =>
        {
            vm.CloseAction = new Action(() => window.Close());
        });
        window.ShowDialog();
    });
}

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

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