2 votes

La barre de défilement de la boîte de liste ne suit pas l'élément sélectionné (avec ICollectionView)

J'essaie de mettre en œuvre le modèle MVVM dans WPF. J'ai suivi les conseils de Jeremy Alles. Application de démonstration MVVM très simple . J'ai une ListBox qui a une liaison avec une ObservableCollection :

<ListBox
    Name="myListBox"
    IsSynchronizedWithCurrentItem="True"
    ItemsSource="{Binding Persons}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <views:PersonsView />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

J'ai ajouté un ICollectionView pour gérer l'élément sélectionné dans la ListBox. Il me permet également d'avoir deux boutons qui me permettent de sélectionner les éléments précédents et suivants de la liste.

private void GoToPrevious()
{
    this.collectionView.MoveCurrentToPrevious();
}
private void GoToNext()
{
    this.collectionView.MoveCurrentToNext();
}

Tout fonctionne parfaitement, mais lorsque l'élément sélectionné se trouve en dessous de la zone affichée de la boîte de liste, la barre de défilement de cette dernière ne se déplace pas en conséquence.

Comment puis-je synchroniser la barre de défilement/zone d'affichage de la ListBox avec l'élément sélectionné ?

6voto

Nelson Reis Points 2889

J'ai trouvé la réponse. J'avais besoin d'utiliser

myListBoxItem.BringIntoView();

Le problème est que je ne voulais pas ajouter de code-behind, car je mets en œuvre MVVM.

La solution consiste à utiliser Comportements attachés . Josh Smith a publié un excellent article à ce sujet : Introduction aux comportements attachés dans WPF .

J'ai ajouté un Setter au style des éléments de la ListBox :

<ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
        <Setter
            Property="custom:ListBoxItemBehavior.IsBroughtIntoViewWhenSelected"
            Value="True" />
    </Style>
</ListBox.ItemContainerStyle>

Et j'ai ajouté la classe suivante (j'ai seulement changé TreeView de l'article de Josh en ListBox) :

public static class ListBoxItemBehavior
{
    #region IsBroughtIntoViewWhenSelected

    public static bool GetIsBroughtIntoViewWhenSelected(ListBoxItem listBoxItem)
    {
        return (bool)listBoxItem.GetValue(IsBroughtIntoViewWhenSelectedProperty);
    }

    public static void SetIsBroughtIntoViewWhenSelected(
      ListBoxItem listBoxItem, bool value)
    {
        listBoxItem.SetValue(IsBroughtIntoViewWhenSelectedProperty, value);
    }

    public static readonly DependencyProperty IsBroughtIntoViewWhenSelectedProperty =
        DependencyProperty.RegisterAttached(
        "IsBroughtIntoViewWhenSelected",
        typeof(bool),
        typeof(ListBoxItemBehavior),
        new UIPropertyMetadata(false, OnIsBroughtIntoViewWhenSelectedChanged));

    static void OnIsBroughtIntoViewWhenSelectedChanged(
      DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        ListBoxItem item = depObj as ListBoxItem;
        if (item == null)
            return;

        if (e.NewValue is bool == false)
            return;

        if ((bool)e.NewValue)
            item.Selected += OnListBoxItemSelected;
        else
            item.Selected -= OnListBoxItemSelected;
    }

    static void OnListBoxItemSelected(object sender, RoutedEventArgs e)
    {
        // Only react to the Selected event raised by the ListBoxItem
        // whose IsSelected property was modified.  Ignore all ancestors
        // who are merely reporting that a descendant's Selected fired.
        if (!Object.ReferenceEquals(sender, e.OriginalSource))
            return;

        ListBoxItem item = e.OriginalSource as ListBoxItem;
        if (item != null)
            item.BringIntoView();
    }

    #endregion // IsBroughtIntoViewWhenSelected
}

Ça marche !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X