Tengo un método de ayuda que utilizo para determinar si un control es parcial o completamente visible dentro de un contenedor primario. Probablemente pueda usarlo con un Converter
para determinar la visibilidad de los elementos.
Su convertidor sería o bien tendrá que calcular el contenedor padre del elemento de interfaz de usuario (Mi blog tiene un conjunto de Visual Tree Helpers que podría ayudar con esto si quiere), o podría ser un MultiConverter
que acepta tanto el elemento de interfaz de usuario y la contenedor principal como parámetros.
ControlVisibility ctrlVisibility=
WPFHelpers.IsObjectVisibleInContainer(childControl, parentContainer);
if (ctrlVisibility == ControlVisibility.Full
|| isVisible == ControlVisibility.FullHeightPartialWidth)
{
return Visibility.Visible;
}
else
{
return = Visibility.Hidden;
}
El código para determinar la visibilidad de un control dentro de sus padres se ve así:
public enum ControlVisibility
{
Hidden,
Partial,
Full,
FullHeightPartialWidth,
FullWidthPartialHeight
}
/// <summary>
/// Checks to see if an object is rendered visible within a parent container
/// </summary>
/// <param name="child">UI element of child object</param>
/// <param name="parent">UI Element of parent object</param>
/// <returns>ControlVisibility Enum</returns>
public static ControlVisibility IsObjectVisibleInContainer(
FrameworkElement child, UIElement parent)
{
GeneralTransform childTransform = child.TransformToAncestor(parent);
Rect childSize = childTransform.TransformBounds(
new Rect(new Point(0, 0), new Point(child.ActualWidth, child.ActualHeight)));
Rect result = Rect.Intersect(
new Rect(new Point(0, 0), parent.RenderSize), childSize);
if (result == Rect.Empty)
{
return ControlVisibility.Hidden;
}
if (Math.Round(result.Height, 2) == childSize.Height
&& Math.Round(result.Width, 2) == childSize.Width)
{
return ControlVisibility.Full;
}
if (result.Height == childSize.Height)
{
return ControlVisibility.FullHeightPartialWidth;
}
if (result.Width == childSize.Width)
{
return ControlVisibility.FullWidthPartialHeight;
}
return ControlVisibility.Partial;
}
Editar
hizo algunas pruebas y, aparentemente, el convertidor se ejecute antes de que los controles están efectivamente prestados. Como un truco, funcionará si usa un MultiConverter
y le pasa el ActualHeight
del control, lo que obligará al convertidor a reevaluar cuando se represente el control.
Aquí está el convertidor de que estaba usando:
public class TestConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
FrameworkElement child = values[0] as FrameworkElement;
var parent = VisualTreeHelpers.FindAncestor<ListBox>(child);
ControlVisibility ctrlVisibility =
VisualTreeHelpers.IsObjectVisibleInContainer(child, parent);
if (ctrlVisibility == ControlVisibility.Full
|| ctrlVisibility == ControlVisibility.FullHeightPartialWidth)
{
return Visibility.Visible;
}
else
{
return Visibility.Hidden;
}
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
{
return null;
}
}
utilicé el XAML informados en su pregunta, y se agregó un estilo implícito para ListBoxItem
en el .Resources
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource Converter}">
<Binding RelativeSource="{RelativeSource Self}" />
<Binding RelativeSource="{RelativeSource Self}" Path="ActualHeight" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
¿Está cambiando lo que ' VirtualizingPanel.ScrollUnit' está configurado en? Porque, de manera predeterminada, está establecido en 'Item', que es lo que estás buscando. Tal vez publiques algunos códigos y capturas de pantalla, y como se trata de una Vista previa del desarrollador, puedes enviar un ticket de problema a Microsoft Connect si es realmente un error. –
Estoy estableciendo explícitamente 'ScrollUnit' en' Item'. Editaré y agregaré mi código de muestra. –
Por lo que sé, es una "característica" de la virtualización. Para la velocidad, no reevalúa el ancho cuando se reutilizan los contenedores de la pantalla. Podría intentar horizontalcontent alignment = stretch.O puede repetir la lista de cadenas y establecer explícitamente el ancho para acomodar el más grande. O bien, puede establecer un ancho fijo que crea que se manejará más y activar el ajuste de texto. – Paparazzi