当另一个控件与其重叠时隐藏控件

时间:2011-09-19 13:37:50

标签: c# wpf windowsformsintegration

我在WPF中托管的Windows窗体控件遇到了很大的问题。例如,当用户滚动窗口时,托管控件会在窗口顶部显示,但应该隐藏它。

我知道这是已知的问题,以及托管控件的默认行为,但我认为如果控件的可见性以某种方式绑定,它可以解决:是否其他控件重叠它。如果其他控件重叠,它应该变为折叠或隐藏,否则,它应该是可见的。

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

2 个答案:

答案 0 :(得分:1)

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

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

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

  1. 使用Windows窗体主机托管其中的其余WPF UI,这意味着我们可以撤销UI的所有权。 WindowsFormsHost必须托管其中包含基于WinForms的滚动查看器的所有UI,而滚动查看器将托管WPF UI。

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

  3. 请告诉我这是否指导您正确的方向。

答案 1 :(得分: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区域裁剪到ScrollViewer上。只需将另一个WindowsFormsHostElementHost放置如下:

<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>

按钮的当前剪辑区域为ElementHostWinForms Button s将在滚动时被其剪辑。 另外,您可以为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>