5

Quindi, sembra davvero sciocco avere una collezione senza cromo se gli elementi vengono tagliati/tagliati alla fine dell'area di scorrimento.Virtualizzazione del pannello che non ritaglia gli articoli

Voglio creare un pannello di virtualizzazione per le raccolte (ItemsControl/ListBox) che disegna solo oggetti interi, mai pezzi di oggetti. Per esempio:

______________ 
|    | 
|______________| 
______________ 
|    | 
|______________| 
______________ 
|    | 

enter image description here

Non voglio il contenitore parziale 3 ° da visualizzare a meno che non ci sia spazio per tutta la voce/contenitore da visualizzare. Negli esempi, il terzo elemento è stato ritagliato a causa della mancanza di spazio.

Qualche suggerimento? Dovrei provare a reinventare la ruota (costruisci il mio)?

EDIT:

Microsoft ha chiarito che VirtualizingPanel.ScrollUnit non è destinato a svolgere questa funzionalità a tutti. Sembra che VirtualizingPanel.ScrollUnit abbia uno scopo molto simile al vecchio CanContentScroll su ScrollViewer.

+0

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? –

+0

Imposo in modo esplicito 'ScrollUnit' a' Item'. Modificherò e aggiungerò il mio codice di esempio. –

+0

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

risposta

4

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> 
+0

ControlVisibility potrebbe essere trasformato in un enumerazione '[Flags]'. Niente cambi di gioco, ma solo un suggerimento. –

+0

Buon post. Grazie! –

+1

@ m-y: Non penso ci sarebbe alcun motivo per renderlo una enumerazione di bandiere. Il valore non dovrebbe mai essere uguale a più di una delle possibilità. Dalla mia comprensione le enumerazioni dei flag sono usate per concatenare più valori insieme a booleano &, |. –

Problemi correlati