Pregunta

Estoy escribiendo una aplicación en .NET que utiliza el desplazamiento automático para un panel de diseño en un diálogo. Parece que cada vez que cambio el tamaño de la ventana para que deberían aparecer las barras de desplazamiento verticales, la barra de desplazamiento horizontal aparece automáticamente también. Mirando de cerca, la segunda barra de desplazamiento ahora me permite desplazar la ventana por 16 píxeles (la anchura de la otra barra de desplazamiento). Así ventanas parece pensar que necesito un área de cliente que es al menos tan amplio como lo era antes de que apareciera la barra de desplazamiento vertical.

Si ahora puedo cambiar el tamaño de la ventana a ser de 16 píxeles más amplia (por lo que mi área de la ventana es tan amplio como lo era antes de que apareciera la barra de desplazamiento), la barra de desplazamiento desaparece. Ahora bien, si puedo cambiar el tamaño de nuevo hacia abajo a lo que era, se queda lejos.

Por lo que me parece que hay un error en el sistema en el que la anchura mínima es de alguna manera pegajosa, pero convertir a SQL Server y downsizging la ventana (con el ratón, y sin tuching las barras de desplazamiento API relacionadas) despeja la condición

¿Alguien sabe de una solución, o estoy haciendo algo para viaje de Windows?

No hay solución correcta

Otros consejos

Sí, creo que ya se diagnostica el problema correctamente. Es un efecto secundario desagradable de, por ejemplo, la barra de desplazamiento vertical que aparece y que necesita espacio, por lo que el área de cliente disponible más pequeño. Demasiado pequeño como para caber los controles, ahora también hacer aparecer la barra de desplazamiento horizontal. En realidad, es bi-estable, la barra horizontal puede parpadeo en y fuera en ciertos casos.

Para evitar este efecto, el motor de renderizado tendría que hacer varias pasadas a través del diseño, se trata de cambiar el área de cliente. No obstante, sólo se hace una sola pasada. Que suena inteligente, esto podría ser potencialmente un bucle sin fin. No sé de una solución decente para esto. Su usuario será probablemente sólo cambiar el tamaño lo suficientemente grande ventana para deshacerse de al menos una de las barras de desplazamiento.

Esto es un error conocido en Windows - aquí

La mejor manera de solucionar este problema es poner el panel de diseño de tabla autosized dentro de otro panel que se acopla a la forma principal y conjunto con desplazamiento automático = true

Así que ya no está utilizando el TableLayoutPanel a rollo que está libre de errores, se utiliza el panel de desplazamiento y TableLayoutPanel está dentro del panel

No he notado exactamente el comportamiento que describes, pero se han encontrado con situaciones en las que la apariencia de la barra de desplazamiento vertical hace una barra de desplazamiento horizontal necesaria.

Se podría establecer el contenido del panel para permitir el ancho de la barra de desplazamiento, por ejemplo si tengo una ListBox en un Panel:

listBox1.Width = panel2.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth;

HTH

Yo sólo encontré con este problema. La solución que utilicé fue al conjunto Scrollable a false y luego a true. He aquí un ejemplo con un evento ListView Resize:

private void myListView_Resize(object sender, EventArgs e)
{
 this.SuspendLayout();

 //Code to do various resizing stuff

 //Force Scrollbar Recalculation
 myListView.Scrollable = false;
 myListView.Scrollable = true;
 this.ResumeLayout(false);
 this.PerformLayout();
}

Si Scrollable no siempre es cierto, puede hacer que el nuevo cálculo condicional.

A pesar de ser una cuestión de edad, sigue siendo un problema en .NET 4. Después de haber leído todo lo que pude encontrar sobre el tema, he quitado una combinación de soluciones en una clase de ayuda.

En primer lugar, aquí es el resultado de que estoy rodando por ... Tengo un panel que contiene una variedad de controles. Los controles secundarios, y sus tamaños pueden cambiar en función de la actividad del usuario. Quiero el panel para cambiar el tamaño horizontal, de modo que nunca hay una barra de desplazamiento horizontal, pero si no hay suficiente espacio en vertical, quiero que aparezca la barra de desplazamiento vertical. Además, la barra de desplazamiento vertical no puede cubrir cualquiera de mis controles secundarios cuando aparece, y no quiero dejar un espacio para que cuando no se necesita.

Los dos 'errores' que mis intentos clase de ayuda para arreglar son en primer lugar, no mostrar la barra de desplazamiento horizontal, y en segundo lugar, cuando el aparece barra de desplazamiento vertical, tienen aumento de la anchura del panel de forma automática para adaptarse a él.

Mi hipótesis es que el panel se establece en AutoSize y desplazamiento automático, y los controles secundarios se establecen para AutoSize también.

La Solución

La clase de ayuda se une al panel (por el manejo de la pintura y eventos SizeChanged) y hace dos cosas. En primer lugar, se desactiva la barra de desplazamiento horizontal. Esto no es tan fácil como parece, y me encontré la solución a este problema aquí barra de desplazamiento horizontal respuesta por KBV Subrahmanyam . En segundo lugar, en respuesta a la pintura y eventos SizeChanged, así como un temporizador de fondo, se comprueba si la propiedad Visible de la barra de desplazamiento vertical ha cambiado. Si es así, se altera la clase de ayuda el derecho de propiedad de relleno del panel para añadir o eliminar el espacio adicional de la barra de desplazamiento requiere. Se requiere el uso de los diversos eventos de la central y el temporizador porque .NET expone no eventos en todo por la barra de desplazamiento (un gran defecto de diseño en mi humilde opinión).

Una vez que el punto final es que no se puede hacer cualquier cosa que cambie el tamaño del panel mientras se manipula el caso SizeChanged. Mal Rollo (tm) sucede si lo hace. Por lo tanto, si necesito cambiar el relleno debido a un evento SizeChanged, programo que el cambio para más adelante.

De todos modos, aquí está el código para la clase de ayuda. Se supone que usted tiene toda la apropiada 'utilizar' las declaraciones, incluyendo una para System.Threading ...

/// <summary>
/// This class is intended to beat the AutoSize and AutoScroll features into submission!
/// 
/// Or, at least getting them to work the way I want them to (which may not be the way 
/// others think they should work).
/// 
/// This class will force a panel that has AutoSize enabled to actually increase its
/// width as appropriate when the AutoScroll Vertical scroll bar becomes visible.
/// I like this better than attempting to 'reserve' space for the Vertical scroll bar,
/// which wastes space when the scroll bar is not needed, and leaves ugly gaps in
/// your user interface.
/// </summary>
public class AutoScrollFixer
{
    /// <summary>
    /// This is the panel we are 'fixing'
    /// </summary>
    private Panel _panel;

    /// <summary>
    /// This field keeps track of the original value for
    /// the right padding property of the panel.
    /// </summary>
    private int _originalRightPadding = 0;

    /// <summary>
    /// We use this flag to prevent recursion problems.
    /// </summary>
    private bool _adjusting = false;

    /// <summary>
    /// This flag keeps track of the last known state of the scroll bar.
    /// </summary>
    private bool _lastScrollBarVisible = false;

    /// <summary>
    /// We use a timer to check the scroll bar state every so often.
    /// This is necessary since .NET (in another stunning piece of
    /// architecture from Microsoft) provides absolutely no events
    /// attached to the scroll bars of a panel.
    /// </summary>
    private System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();

    /// <summary>
    /// Construct an AutoScrollFixer and attach it to the provided panel.
    /// Once created, there is no particular reason to keep a reference 
    /// to the AutoScrollFixer in your code.  It will silently do its thing
    /// in the background.
    /// </summary>
    /// <param name="panel"></param>
    public AutoScrollFixer(Panel panel)
    {
        _panel = panel;
        _originalRightPadding = panel.Padding.Right;

        EnableVerticalAutoscroll(_panel);
        _lastScrollBarVisible = _panel.VerticalScroll.Visible;

        _panel.Paint += (s, a) =>
        {
            AdjustForVerticalScrollbar();
        };

        _panel.SizeChanged += (s, a) =>
        {
            //
            //  We can't do something that changes the size while handling
            //  a size change.  So, if an adjustment is needed, we will
            //  schedule it for later.
            //
            if (_lastScrollBarVisible != _panel.VerticalScroll.Visible)
            {
                AdjustLater();
            }
        };

        _timer.Tick += (s, a) =>
        {
            //
            //  Sadly, the combination of the Paint event and the SizeChanged event
            //  is NOT enough to guarantee that we will catch a change in the
            //  scroll bar status.  So, as a last ditch effort, we will check
            //  for a status change every 500 mSecs.  Yup, this is a hack!
            //
            AdjustForVerticalScrollbar();
        };

        _timer.Interval = 500;
        _timer.Start();
    }


    /// <summary>
    /// Enables AutoScroll, but without the Horizontal Scroll bar.
    /// Only the Vertical Scroll bar will become visible when necessary
    /// 
    /// This method is based on this StackOverflow answer ...
    /// https://stackoverflow.com/a/28583501/2175233
    /// </summary>
    /// <param name="panel"></param>
    public static void EnableVerticalAutoscroll( Panel panel )
    {
        panel.AutoScroll = false;
        panel.HorizontalScroll.Enabled = false;
        panel.HorizontalScroll.Visible = false;
        panel.HorizontalScroll.Maximum = 0;
        panel.AutoScroll = true;
    }


    /// <summary>
    /// Queue AdjustForVerticalScrollbar to run on the GUI thread after the current
    /// event has been handled.
    /// </summary>
    private void AdjustLater()
    {
        ThreadPool.QueueUserWorkItem((t) => 
        {
            Thread.Sleep(200);
            _panel.BeginInvoke((Action)(() =>
            {
                AdjustForVerticalScrollbar();
            }));
        });
    }


    /// <summary>
    /// This is where the real work gets done.  When this method is called, we will
    /// simply set the right side padding on the panel to make room for the
    /// scroll bar if it is being displayed, or reset the padding value to 
    /// its original value if not.
    /// </summary>
    private void AdjustForVerticalScrollbar()
    {
        if (!_adjusting)
        {
            try
            {
                _adjusting = true;

                if (_lastScrollBarVisible != _panel.VerticalScroll.Visible)
                {
                    _lastScrollBarVisible = _panel.VerticalScroll.Visible;

                    Padding p = _panel.Padding;
                    p.Right = _lastScrollBarVisible ? _originalRightPadding + System.Windows.Forms.SystemInformation.VerticalScrollBarWidth + 2 : _originalRightPadding;
                    _panel.Padding = p;
                    _panel.PerformLayout();
                }
            }

            finally
            {
                _adjusting = false;
            }
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top