Ho un metodo di supporto che utilizzo per determinare se un controllo è parzialmente o completamente visibile all'interno di un contenitore padre. Probabilmente puoi usarlo con un Converter
per determinare la visibilità degli oggetti.
il convertitore dovrà o per calcolare il contenitore padre dalla voce UI (Il mio blog ha una serie di Visual Tree Helpers che potrebbe aiutare con questo se si vuole), o potrebbe essere un MultiConverter
che accetta sia l'elemento dell'interfaccia utente e la contenitore genitore come parametri.
ControlVisibility ctrlVisibility=
WPFHelpers.IsObjectVisibleInContainer(childControl, parentContainer);
if (ctrlVisibility == ControlVisibility.Full
|| isVisible == ControlVisibility.FullHeightPartialWidth)
{
return Visibility.Visible;
}
else
{
return = Visibility.Hidden;
}
Il codice per determinare la visibilità di un controllo all'interno del suo genitore assomiglia a questo:
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;
}
Modifica
fatto alcuni test e apparentemente il convertitore venga eseguito prima che i controlli vengano effettivamente resi. Come un hack, funzionerà se si utilizza un MultiConverter
e si passa il ActualHeight
del controllo, che costringerà il convertitore a rivalutare quando viene eseguito il rendering del controllo.
Ecco il convertitore usavo:
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;
}
}
ho usato il codice XAML avete inviato nella sua interrogazione, e appena aggiunto uno stile implicito per ListBoxItem
nel .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>
Stai cambiando quello che ' VirtualizingPanel.ScrollUnit' è impostato su? Perché, per impostazione predefinita, è impostato su "Elemento", che è ciò che stai cercando. Magari postare codice e screenshot, e dal momento che si tratta di un'anteprima dello sviluppatore, potresti inviare un ticket di problemi a Microsoft Connect se è davvero un bug? –
Imposo in modo esplicito 'ScrollUnit' a' Item'. Modificherò e aggiungerò il mio codice di esempio. –
Da quello che so è una "caratteristica" della virtualizzazione. Per la velocità, non rivaluta la larghezza quando i contenitori dello schermo vengono riutilizzati. Potresti provare l'allineamento del contenuto orizzontale = allungare.Oppure è possibile scorrere l'elenco di stringhe e impostare esplicitamente la larghezza per adattarla al più grande. Oppure puoi impostare una larghezza fissa che pensi possa gestire di più e attivare il text wrapping. – Paparazzi