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 会越过它的父控件。我试过将它放在不同类型的控件中,例如 DockPanel
和 Grid
,一切都以相同的方式运行。
是否有特殊的方法可以使其正常运行?
如果需要更多代码,我很乐意 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 渲染,所以没有办法解决。
首先介绍一下背景知识,我有一个使用 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 会越过它的父控件。我试过将它放在不同类型的控件中,例如 DockPanel
和 Grid
,一切都以相同的方式运行。
是否有特殊的方法可以使其正常运行?
如果需要更多代码,我很乐意 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 渲染,所以没有办法解决。