MAF 插件 UI 内容在主应用程序中滚动到边界之外

MAF Plugin UI content scrolling outside of bounds in main application

首先介绍一下背景知识,我有一个使用 Microsoft AddIn Framework (MAF) 的应用程序,它从插件中获取 WPF UI(您可以按照 this Microsoft example 创建一个) .在插件内容足够大以至于主窗体需要滚动之前,这已经启动并且工作正常。发生这种情况时,它会滚动到应有的范围之外。

在图像中,您会注意到当您向下滚动一些时 Plugin Label Top 会超过 Main Label Top,而在底部您只会看到 Plugin Label Bottom。我的主窗体代码如下:

<Window x:Class="WpfAddinTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfAddinTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525" Background="DarkGray">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="25"/>
            <RowDefinition/>
            <RowDefinition Height="25"/>
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Content="Main Label Top"/>

        <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
            <ContentControl Name="PluginHolder"/>
        </ScrollViewer>

        <Label Grid.Row="2" Content="Main Label Bottom"/>

    </Grid>
</Window>

ContentControl 是插件 UI 的所在,我不明白为什么插件 UI 会越过它的父控件。我试过将它放在不同类型的控件中,例如 DockPanelGrid,一切都以相同的方式运行。

是否有特殊的方法可以使其正常运行?

如果需要更多代码,我很乐意 post 它,https://github.com/middas/WpfAddInTest 是我演示这一点的完整示例项目。

编辑: 在 WPF Inspector 中加载表单,我只能看到一个 AddInHost 控件,它没有显示ContentControl。这和它有关系吗?

编辑 2: 在尝试我能想到的任何事情时,我在想可能是它在放置控件时没有获得正确的高度,所以我有插入 return 所需的高度,并根据 return 编辑的内容手动设置 ContentPlaceholder 的高度;没运气。这是我尝试过的:

我将 AddIn 合同从 GetInt() 更新为 GetHeight() 并且在插件上我现在有这个方法:

public double GetHeight()
{
    _Control.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

    return _Control.DesiredSize.Height;
}

然后在托管表格上,我现在有这个:

public MainWindow()
{
    _PluginPath = System.IO.Path.Combine(Environment.CurrentDirectory, "Pipeline");
    _AddInPath = System.IO.Path.Combine(_PluginPath, "AddIns");

    InitializeComponent();

    var warnings = new List<string>(AddInStore.Update(_PluginPath));

    _PluginToken = AddInStore.FindAddIns(typeof(IPlugin), _PluginPath, _AddInPath).FirstOrDefault();
    _Plugin = _PluginToken.Activate<IPlugin>(AddInSecurityLevel.FullTrust);

    var control = _Plugin.GetControl();
    PluginHolder.Height = _Plugin.GetHeight();

    PluginHolder.Content = control;
}

编辑 3: 尝试强制 ZIndex 似乎也不会影响它。

Panel.SetZIndex(control, -1);

我相信我终于弄明白了这个问题。我认为问题是因为插件 UI 在 AppDomain 之外,ScrollViewer 不知道如何正确剪辑内容。我最终所做的工作是创建一个回调到主UI,插件可以使用它来获得它需要适应的高度。如果插件需要滚动,插件可以自己处理它ScrollViewer.

这是更新后的合同:

[AddInContract]
public interface IPluginContract : IContract
{
    INativeHandleContract GetControl();

    double GetHeight();

    void SetHostCallback(IHostCallbackContract callback);
}

IHostCallbackContract:

public interface IHostCallbackContract : IContract
{
    double GetHeight();
}

现在在插件returns之前Control它可以设置主窗体给定的高度:

public FrameworkElement GetControl()
{
    if (_Callback != null)
    {
        _Control.SetHeight(_Callback.GetHeight());
    }

    return _Control;
}

我已经用整个工作解决方案更新了我的 Git 存储库 (https://github.com/middas/WpfAddInTest)。现在唯一的问题是滚动不是双缓冲的,所以它会闪烁。我将不得不接受它,因为它没有出现,但由于通过 DirectX 进行 WPF 渲染,所以没有办法解决。