【问题标题】:Hide control when another control overlaps it当另一个控件重叠时隐藏控件
【发布时间】:2011-09-19 13:37:50
【问题描述】:

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

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

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

【问题讨论】:

    标签: c# wpf windowsformsintegration


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

    • 感谢您的回答。第一种方法对我来说太复杂了,因为我们有太多的观点需要改变。我尝试了第二个选项,但我对结果不满意。我认为您的解决方案更好。你能给我一些代码指南,或者至少是伪代码吗?它会为我节省很多时间。
    【解决方案2】:

    你可以做一个小把戏。当您声明 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 项目以在ScrollViewer 上剪辑WinForms 区域。只需将另一个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 Buttons 将在滚动时被剪辑。 您也可以为ContentContol 创建ControlTemplate 并在需要的地方重复使用它。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多