4

我对 WPF 中托管的 Windows 窗体控件有很大的问题。例如,当用户滚动窗口时,托管控件位于窗口顶部,尽管它应该被隐藏。

我知道这是已知问题,也是托管控件的默认行为,但我认为如果控件的可见性以某种方式与以下内容绑定,则可以解决:其他控件是否与它重叠。如果其他控件重叠,则应为 Collapsed 或 Hidden,否则应为 Visible。

我为此做了某种解决方案,但是我在 ScrollViewer 的 ScrollChanged 事件上做了它,它只在特殊情况下有效。如果有人知道如何通过绑定来实现这一点,那么它可以应用于任何托管控件,请分享您的想法。

4

2 回答 2

1

对于同样的问题,我们实现了一些奇怪的东西......

Windows 窗体主机不受 Z 顺序的影响,因此滚动查看器将无法在滚动查看器下可见的区域部分隐藏/剪辑它。

所以我们有两个选择...

  1. 使用 Windows 窗体主机在其中托管 WPF UI 的其余部分,这意味着我们反转 UI 的所有权。WindowsFormsHost 必须在其中托管所有 UI,并具有基于 WinForms 的滚动查看器,该滚动查看器反过来将托管 WPF UI。

  2. 为 windows 窗体主机的计算高度实现滚动偏移量,当用户滚动时,将此偏移量添加到滚动查看器的位置并自己隐藏windforms 主机(Visibility = Hidden不是 Collapsed)。这样,它会产生一种效果,即您不能部分滚动 winforms 主机,而是将其完全滚动到滚动查看器之外。并且由于 winformshost 是Hidden(未折叠)它继续在滚动查看器下方的不可见区域内占据如此高的高度(从而保持其滚动位置)。

让我知道这是否会引导您朝着正确的方向前进。

于 2011-09-20T08:26:59.020 回答
0

你可以做一个小技巧。当您声明一个WindowsFormsHost时,它的父级是第一个 HWND 组件。通常它是根窗口。因此,控件的剪辑区域是整个窗口。我将展示一个 WPF 示例ScrollViewer

<Window>
    <Grid>
        <ScrollViewer Margin="20,50">
            <ItemsControl ItemsSource="{StaticResource StringArray}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <WindowsFormsHost>
                            <wf:Button />
                        </WindowsFormsHost>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </Grid>
</Window>

在这种情况下,行为将与您描述的一样。按钮将超出ScrollViewer范围。但是有一种方法可以创建“中间”HWND 项目来剪辑WinForms区域ScrollViewerWindowsFormsHost只需ElementHost像下面这样放置另一个:

<Grid>
    <WindowsFormsHost Margin="20,50">
        <ElementHost x:Name="This is clip container">
            <ScrollViewer>
                <ItemsControl ItemsSource="{StaticResource StringArray}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <WindowsFormsHost>
                                <wf:Button />
                            </WindowsFormsHost>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </ScrollViewer>
        </ElementHost>
    </WindowsFormsHost>
</Grid>

现在按钮的剪辑区域 isElementHostWinForms Buttons 将在滚动时被它剪辑。ControlTemplate您也可以在需要的地方创建ContentContol和重用它。

<ControlTemplate x:Key="ClipConteiner" TargetType="{x:Type ContentControl}">
    <WindowsFormsHost>
        <ElementHost>
            <ContentPresenter />
        </ElementHost>
    </WindowsFormsHost>
</ControlTemplate>
<Grid>
    <ContentControl Template="{StaticResource ClipConteiner}" Margin="20,50">
        <ScrollViewer>
            <ItemsControl ItemsSource="{StaticResource StringArray}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <WindowsFormsHost>
                            <wf:Button />
                        </WindowsFormsHost>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </ContentControl>
</Grid>
于 2020-04-03T15:01:02.937 回答