wpf listbox scroll grouping wrappanel

WPF ListBox WrapPanel clips largos grupos



scroll grouping (4)

Al establecer la propiedad Height en el WrapPanel a la altura del ScrollContentPresenter, nunca se desplazará verticalmente. Sin embargo, si quita ese enlace, nunca se ajustará, ya que en el pase de diseño tiene una altura infinita para el diseño.

Sugeriría crear tu propia clase de panel para obtener el comportamiento que deseas. Disponga de una propiedad de dependencia independiente a la que pueda vincular la altura deseada, de modo que pueda usarla para calcular la altura del objetivo en la medida y organizar los pasos. Si un niño es más alto que la altura deseada, use la altura de ese niño como la altura objetivo para calcular la envoltura.

Aquí hay un panel de ejemplo para hacer esto:

public class SmartWrapPanel : WrapPanel { /// <summary> /// Identifies the DesiredHeight dependency property /// </summary> public static readonly DependencyProperty DesiredHeightProperty = DependencyProperty.Register( "DesiredHeight", typeof(double), typeof(SmartWrapPanel), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); /// <summary> /// Gets or sets the height to attempt to be. If any child is taller than this, will use the child''s height. /// </summary> public double DesiredHeight { get { return (double)GetValue(DesiredHeightProperty); } set { SetValue(DesiredHeightProperty, value); } } protected override Size MeasureOverride(Size constraint) { Size ret = base.MeasureOverride(constraint); double h = ret.Height; if (!Double.IsNaN(DesiredHeight)) { h = DesiredHeight; foreach (UIElement child in Children) { if (child.DesiredSize.Height > h) h = child.DesiredSize.Height; } } return new Size(ret.Width, h); } protected override System.Windows.Size ArrangeOverride(Size finalSize) { double h = finalSize.Height; if (!Double.IsNaN(DesiredHeight)) { h = DesiredHeight; foreach (UIElement child in Children) { if (child.DesiredSize.Height > h) h = child.DesiredSize.Height; } } return base.ArrangeOverride(new Size(finalSize.Width, h)); } }

Creé un ListBox para mostrar elementos en grupos, donde los grupos se envuelven de derecha a izquierda cuando ya no caben dentro del alto del panel de ListBox. Entonces, los grupos aparecerían de manera similar en el cuadro de lista, donde la altura de cada grupo es arbitraria (el grupo 1, por ejemplo, es dos veces más alto que el grupo 2):

[ 1 ][ 3 ][ 5 ] [ ][ 4 ][ 6 ] [ 2 ][ ]

El siguiente XAML funciona correctamente porque realiza el ajuste y permite que la barra de desplazamiento horizontal aparezca cuando los elementos se ejecutan en el lado derecho del ListBox.

<ListBox> <ListBox.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Vertical"/> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.GroupStyle> <ItemsPanelTemplate> <WrapPanel Orientation="Vertical" Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ScrollContentPresenter}}}"/> </ItemsPanelTemplate> </ListBox.GroupStyle> </ListBox>

El problema ocurre cuando un grupo de artículos es más largo que la altura del WrapPanel. En lugar de permitir que la barra de desplazamiento vertical parezca ver el grupo de elementos de corte, los elementos de ese grupo simplemente se recortan. Supongo que este es un efecto secundario del enlace de Altura en el WrapPanel: la barra de desplazamiento cree que no tiene que estar habilitado.

¿Hay alguna forma de habilitar la barra de desplazamiento, o de otra manera alrededor de este problema que no estoy viendo?


Aquí está el código ligeramente modificado, todo el crédito otorgado a Abe Heidebrecht, quien lo publicó anteriormente, que permite el desplazamiento horizontal y vertical. El único cambio es que el valor de retorno de MeasureOverride debe ser base.MeasureOverride (new Size (ret.width, h)).

// Original code : Abe Heidebrecht public class SmartWrapPanel : WrapPanel { /// <summary> /// Identifies the DesiredHeight dependency property /// </summary> public static readonly DependencyProperty DesiredHeightProperty = DependencyProperty.Register( "DesiredHeight", typeof(double), typeof(SmartWrapPanel), new FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); /// <summary> /// Gets or sets the height to attempt to be. If any child is taller than this, will use the child''s height. /// </summary> public double DesiredHeight { get { return (double)GetValue(DesiredHeightProperty); } set { SetValue(DesiredHeightProperty, value); } } protected override Size MeasureOverride(Size constraint) { Size ret = base.MeasureOverride(constraint); double h = ret.Height; if (!Double.IsNaN(DesiredHeight)) { h = DesiredHeight; foreach (UIElement child in Children) { if (child.DesiredSize.Height > h) h = child.DesiredSize.Height; } } return base.MeasureOverride(new Size(ret.Width, h)); } protected override System.Windows.Size ArrangeOverride(Size finalSize) { double h = finalSize.Height; if (!Double.IsNaN(DesiredHeight)) { h = DesiredHeight; foreach (UIElement child in Children) { if (child.DesiredSize.Height > h) h = child.DesiredSize.Height; } } return base.ArrangeOverride(new Size(finalSize.Width, h)); } }


Creo que tienes razón en que tiene que ver con el enlace. ¿Qué sucede cuando quitas el enlace? Con el enlace, ¿está intentando llenar al menos toda la altura del cuadro de lista? De ser así, considere enlazar a MinHeight en su lugar, o intente usar la propiedad VerticalAlignment .


Gracias por responder, David.

Cuando se removed el enlace, no se produce ningún ajuste. El WrapPanel coloca a cada grupo en una sola columna vertical.

El enlace está destinado a obligar al WrapPanel a envolver realmente. Si no se establece ningún enlace, WrapPanel supone que la altura es infinita y nunca se ajusta.

La vinculación a MinHeight da MinHeight resultado un cuadro de lista vacío. Puedo ver cómo la propiedad VerticalAlignment podría parecer una solución, pero la alineación misma evita que se produzca ningún ajuste. Cuando el enlace y la alineación se usan juntos, la alineación no tiene ningún efecto sobre el problema.