Ho cercato di ottenere un ItemsControl con un VirtualizingStackPanel per spostarsi su un elemento per un po 'di tempo, e continuai a trovare il "usa un ListBox" risposta. Non volevo, quindi ho trovato un modo per farlo. Per prima cosa devi configurare un modello di controllo per il tuo ItemsControl che contiene un ScrollViewer (che probabilmente hai già se usi un controllo per gli oggetti). Il mio modello di base sia simile alla seguente (contenuto in uno stile a portata di mano per l'ItemsControl)
<Style x:Key="TheItemsControlStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False" HorizontalScrollBarVisibility="Auto">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
così ho fondamentalmente ha un confine con un visualizzatore di scorrimento thats di andare a contenere il mio contenuto.
mio ItemsControl è definita con:
<ItemsControl x:Name="myItemsControl" [..snip..] Style="{DynamicResource TheItemsControlStyle}" ScrollViewer.CanContentScroll="True" VirtualizingStackPanel.IsVirtualizing="True">
Ok ora la parte divertente. Ho creato un metodo di estensione per collegare a qualsiasi ItemsControl per farlo scorrere fino alla voce data:
public static void VirtualizedScrollIntoView(this ItemsControl control, object item) {
try {
// this is basically getting a reference to the ScrollViewer defined in the ItemsControl's style (identified above).
// you *could* enumerate over the ItemsControl's children until you hit a scroll viewer, but this is quick and
// dirty!
// First 0 in the GetChild returns the Border from the ControlTemplate, and the second 0 gets the ScrollViewer from
// the Border.
ScrollViewer sv = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild((DependencyObject)control, 0), 0) as ScrollViewer;
// now get the index of the item your passing in
int index = control.Items.IndexOf(item);
if(index != -1) {
// since the scroll viewer is using content scrolling not pixel based scrolling we just tell it to scroll to the index of the item
// and viola! we scroll there!
sv.ScrollToVerticalOffset(index);
}
} catch(Exception ex) {
Debug.WriteLine("What the..." + ex.Message);
}
}
Quindi, con il metodo di estensione in atto lo si dovrebbe utilizzare come metodo di compagno di ListBox:
myItemsControl.VirtualizedScrollIntoView(someItemInTheList);
Funziona alla grande!
Nota che puoi anche chiamare sv.ScrollToEnd() e gli altri metodi di scorrimento usuali per aggirare i tuoi articoli.
fonte
2012-11-28 04:11:21
Vorrei evitare di farlo perché non ho bisogno della funzionalità "seleziona un elemento" di "ListBox".Qualche idea sul perché 'ItemsControl' non ha' ScrollIntoView'? –
@Seth: Come ho detto, puoi nascondere la selezione, a chi importa se è lì? Non ha lo scrolling perché è stato progettato in questo modo, 'ItemsControl' è il più basilare dei controlli degli elementi, la funzionalità di scorrimento non è necessaria per una classe di base. –
Ora per scoprire come fare in modo che 'ListBox' lasci scorrere completamente un oggetto in vista quando si fa clic ... –