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

时间:2017-11-03 06:03:28

标签: c# wpf maf

首先,我有一个应用程序使用Microsoft AddIn Framework(MAF)从插件获取WPF UI(您可以按this Microsoft example创建一个)。这个工作正常,直到插件内容足够大,主表单需要滚动。当发生这种情况时,它会滚动到它应该的边界之外。

Out of bounds scrolling image

在图片中,当您向下滚动时,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是插件用户界面的内容,我不明白为什么插件用户界面会覆盖它的父控件。我尝试将其置于不同类型的控件中,例如DockPanelGrid,一切都以相同的方式运行。

是否有一种特殊的方法可以让它正常运作?

如果需要更多代码,我很乐意发布,https://github.com/middas/WpfAddInTest是我完整的示例项目,可以证明这一点。

编辑:在WPF检查器中加载表单,我只能看到AddInHost控件,它不会显示ContentControl中的任何单个控件。这与它有关吗? WPF Inspector

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

我已将GetInt()的AddIn合约更新为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);

1 个答案:

答案 0 :(得分:0)

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

以下是更新后的合同:

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

    double GetHeight();

    void SetHostCallback(IHostCallbackContract callback);
}

IHostCallbackContract:

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

现在,在插件返回Control之前,它可以设置主窗体给出的高度:

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

    return _Control;
}

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