弹出窗口中的选项卡导航损坏,WPF 用户控件托管在默认 AppDomain 中的 Winforms 中 [英] Broken tab navigation in popup with WPF user control hosted inside Winforms in default AppDomain

查看:16
本文介绍了弹出窗口中的选项卡导航损坏,WPF 用户控件托管在默认 AppDomain 中的 Winforms 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用弹出窗口的 WPF 用户控件.此控件是一个插件,可以加载到主 AppDomain 或单独的 AppDomain 中,并使用 ElementHost 托管在 Winforms 窗体中.当在主 AppDomain 中加载插件并打开弹出窗口时,在弹出窗口的字段之间切换,而是将焦点移至弹出窗口父级的第一个控件.当它加载到新的 AppDomain 中时,选项卡行为按预期/期望工作(它在弹出窗口中的控件之间循环).

I have a WPF user control that uses a Popup. This control is a plugin and can be loaded in the main AppDomain or in a separate AppDomain, and it is hosted in a Winforms form using ElementHost. When the plugin is loaded in the main AppDomain, and the popup is opened, tabbing between the fields of the popup instead moves focus to the first control of the popup windows parent. When it is loaded in a new AppDomain, the tab behavior works as expected/desired (it cycles through the controls in the popup window).

我在 SO 和其他地方阅读了许多类似但不完全相同的问题,但没有任何建议有帮助.

I have read through many similar, but not quite the same, questions here on SO and elsewhere, but none of the suggestions have helped.

似乎在 AddInHost 中处理选项卡消息(这来自我使用 FrameworkElementAdapters 在域外情况下跨域边界封送 WPF 控件).我的最终目标是将其作为托管加载项框架加载项来实现,但我已经缩减了这种方式以简化重现.

It appears that the tab message is getting handled in the AddInHost (which comes from my use of FrameworkElementAdapters to marshal the WPF control across domain boundaries in out-of-domain case). My ultimate goal is to implement this as a Managed Add-in Framework addin, but I have pared that WAY down to simplify the repro.

如果有更完整的上下文有帮助,我有一个简化 repro 的 git repo

In case it helps to have a more complete context, I have a git repo of the simplified repro

我该怎么做才能使这种行为保持一致?

What can I do to make this behavior consistent?

WpfUserControl.xaml

<UserControl x:Class="MyPlugin.WpfUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         mc:Ignorable="d" Background="White">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="28" />
            <RowDefinition Height="28" />
            <RowDefinition Height="28" />
        </Grid.RowDefinitions>

        <TextBox Grid.Row="0" Margin="3" />

        <Button x:Name="DropDownButton" Grid.Row="1" Margin="3" HorizontalAlignment="Left" MinWidth="100" Content="Drop Down" Click="DropDownButton_OnClick" />
        <Popup Grid.Row="1" x:Name="Popup1" Placement="Right" StaysOpen="True" PlacementTarget="{Binding ElementName=DropDownButton}">
            <Border BorderBrush="Black" BorderThickness="1">
                <Grid Background="White">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <Label Content="Username:" Grid.Row="0" Grid.Column="0" Margin="3" />
                    <TextBox Grid.Row="0" Grid.Column="1" Margin="3" MinWidth="150" />

                    <Label Content="Password:" Grid.Row="1" Grid.Column="0" Margin="3" />
                    <TextBox Grid.Row="1" Grid.Column="1" Margin="3" MinWidth="150" />

                    <Button x:Name="SaveButton" Grid.Row="2" Grid.Column="1" Margin="3" HorizontalAlignment="Right"
                                            Content="Save" Click="SaveButton_OnClick" />
                </Grid>
            </Border>
        </Popup>

        <Button x:Name="DoSomethingButton" Grid.Row="2" Margin="3" HorizontalAlignment="Left" MinWidth="100" Content="Do Something" />
    </Grid>
</UserControl>

插件.cs

public class Plugin : MarshalByRefObject
{
    public INativeHandleContract CreateWpfUserControl()
    {
        return FrameworkElementAdapters.ViewToContractAdapter(new WpfUserControl());
    }
}

MainForm.cs(选定的位)

private void LoadPlugin(bool loadInSameAppDomain)
{
    AppDomain appDomain;
    if (loadInSameAppDomain)
    {
        appDomain = AppDomain.CurrentDomain;
    }
    else
    {
        var appDomainName = Guid.NewGuid().ToString();
        _appDomain = AppDomain.CreateDomain(appDomainName, AppDomain.CurrentDomain.Evidence, new AppDomainSetup
        {
            ApplicationName = appDomainName,
            ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
            PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory
        });
        appDomain = _appDomain;
    }

    _plugin = (Plugin)appDomain.CreateInstanceAndUnwrap("MyPlugin", "MyPlugin.Plugin");
}

private void loadPluginButton_Click(object sender, EventArgs e)
{
    LoadPlugin(appDomainCheckBox.Checked);

    var pluginControl = FrameworkElementAdapters.ContractToViewAdapter(_plugin.CreateWpfUserControl());
    elementHost1.Child = pluginControl;

    UpdateUi(true);
}

推荐答案

我有点受过教育,但绝不是权威,猜测是问题在于 WinForms 和 WPF 希望对顶部窗口的消息泵有独占访问权.在其自己的 AppDomain 中运行每一个,给予每个父窗口及其消息泵的独占控制.

My somewhat educated, though by no means authoritative, guess is that the issue is that WinForms and WPF expect to have exclusive access to the top window's message pump. Running each in its own AppDomain gives each exclusive control of a parent window and its message pump.

这篇关于弹出窗口中的选项卡导航损坏,WPF 用户控件托管在默认 AppDomain 中的 Winforms 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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