如何阻止 Winforms 面板滚动?

Posted

技术标签:

【中文标题】如何阻止 Winforms 面板滚动?【英文标题】:How can you stop a Winforms Panel from scrolling? 【发布时间】:2010-09-30 00:07:35 【问题描述】:

如果您将一个 400 像素高的 DataGridView 放在一个 300 像素高的面板上,这样面板上就会有一个滚动条,然后向下滚动以显示网格的下半部分,然后单击一个控件在面板外,然后单击网格中的一行,面板向上滚动到顶部并选择了网格中的错误行。

它不仅仅是一个 DataGridView;它发生在任何高于面板的控件上,例如 Infragistics UltraWinGrid、Rich Text Box。我将其作为 Infragistics 的错误提出,但他们说这是 Microsoft 的问题。

我已尝试使用控件的所有相关事件,但面板滚动发生在事件触发之前。

有什么建议吗?

【问题讨论】:

【参考方案1】:

我理解你的痛苦,这让我不止一次。

如果您的 DataGridView 是面板中唯一的内容,只需将 Dock 设置为 Fill 并让 DGV 自行处理滚动。我认为它不会再做跳跃的事情了。否则,我想你可以调整它的大小,让它小于面板,让它自己滚动。

【讨论】:

【参考方案2】:

我猜您正在将面板的 AutoScroll 属性设置为 true。当您这样做时,切换应用程序会将滚动位置重置为零,并且面板会重置其位置。

如果您关闭 AutoScroll 并添加自己的滚动条,您可以设置滚动条的最大值和最小值以匹配面板的要求,然后在滚动条的 Scroll 事件中设置面板的滚动值。切换窗口时不会重置。

类似:

private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)

    panel1.VerticalScroll.Value = vScrollBar1.Value;

这对我来说是一个新的,我不得不重新创建它。我可能需要在我的网站上添加一篇关于它的文章 :-)

【讨论】:

谢谢你 - 它看起来很有希望。我们在使用 VScrollBar 时遇到了一些闪烁问题,但我相信我们可以想出一些可行的方法。它肯定会停止原来的跳跃问题。【参考方案3】:

这是由于 ScrollToControl 事件由 ScrollableControl 类自动触​​发,并且事件处理程序滚动以显示获得焦点的控件的左上角。当可滚动容器控件仅包含一个控件时,此行为没有帮助。我对这种行为感到非常沮丧,直到我找到了阻止它的方法。

停止这种行为的方法是重写 ScrollToControl 事件处理程序,如下所示:

class PanelNoScrollOnFocus : Panel

    protected override System.Drawing.Point ScrollToControl(Control activeControl)
    
        return DisplayRectangle.Location;
    

用此面板控件替换您的面板控件。 完成。

【讨论】:

谢谢,过去一个小时我的头一直在桌子上。您的解决方案节省了去医院的行程! :) 谢谢!这是我需要的解决方案。 我该如何实现这个? 首先,将此类添加到您的项目中。 (创建一个新的空类文件并粘贴上面的代码。)然后转到表单设计器并查看工具箱。您现在应该会在此处看到一个新控件 PanelNoScrollOnFocus。将其拖到画布上;使用它作为您的面板,而不是使用香草面板。要更改现有表单,请手动编辑 .designer.cs 文件;搜索“System.Windows.Forms.Panel”并将其替换为 PanelNoScrollOnFocus 用于您想要此行为的每个面板。 完美的解决方案,而且代码很少。【参考方案4】:

感谢 skypecakes,效果很好 :) 这是您的控件的编辑版本,它还跟踪滚动条的位置:

class AutoScrollPanel : Panel

    public AutoScrollPanel()
    
        Enter += PanelNoScrollOnFocus_Enter;
        Leave += PanelNoScrollOnFocus_Leave;
    

    private System.Drawing.Point scrollLocation;

    void PanelNoScrollOnFocus_Enter(object sender, System.EventArgs e)
    
        // Set the scroll location back when the control regains focus.
        HorizontalScroll.Value = scrollLocation.X;
        VerticalScroll.Value = scrollLocation.Y;
    

    void PanelNoScrollOnFocus_Leave(object sender, System.EventArgs e)
    
        // Remember the scroll location when the control loses focus.
        scrollLocation.X = HorizontalScroll.Value;
        scrollLocation.Y = VerticalScroll.Value;
    

    protected override System.Drawing.Point ScrollToControl(Control activeControl)
    
        // When there's only 1 control in the panel and the user clicks
        //  on it, .NET tries to scroll to the control. This invariably
        //  forces the panel to scroll up. This little hack prevents that.
        return DisplayRectangle.Location;
    

这只有在面板中只有一个控件时才有效(尽管我没有测试过不止一个控件)。

【讨论】:

以上是关于如何阻止 Winforms 面板滚动?的主要内容,如果未能解决你的问题,请参考以下文章

如何在页面滚动时获取嵌套面板的相对坐标

C# WinForms 面板子定位非常不稳定?

WinForms:寻找一种简单的方法来弹出“正在处理..”面板

自动滚动面板到底部

将垂直滚动条添加到面板

当我进行 api 调用时如何阻止 winforms 应用程序冻结