Bonjour,

Je souhaite avoir la possibilité d'un autoscrool de ma listbox en respectant le MVVM.

J'ai trouvé une classe qui permettrait de créer un Control basé sur une listbox en ajoutant cette fonction, mais comme souvent elle est en C# et malgré mes essaies j'ai toujours une erreur.

Voici la classe en C#

Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public class LoggingListBox : ListBox
{
    ///<summary>
    ///Define the AutoScroll property. If enabled, causes the ListBox to scroll to 
    ///the last item whenever a new item is added.
    ///</summary>
    public static readonly DependencyProperty AutoScrollProperty = 
        DependencyProperty.Register(
            "AutoScroll", 
            typeof(Boolean), 
            typeof(LoggingListBox), 
            new FrameworkPropertyMetadata(
                true, //Default value.
                FrameworkPropertyMetadataOptions.AffectsArrange | 
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                AutoScroll_PropertyChanged));
 
    /// <summary>
    /// Gets or sets whether or not the list should scroll to the last item 
    /// when a new item is added.
    /// </summary>
    [Category("Common")] //Indicate where the property is located in VS designer.
    public bool AutoScroll
    {
        get { return (bool)GetValue(AutoScrollProperty); }
        set { SetValue(AutoScrollProperty, value); }
    }
 
    /// <summary>
    /// Event handler for when the AutoScroll property is changed.
    /// This delegates the call to SubscribeToAutoScroll_ItemsCollectionChanged().
    /// </summary>
    /// <param name="d">The DependencyObject whose property was changed.</param>
    /// <param name="e">Change event args.</param>
    private static void AutoScroll_PropertyChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        SubscribeToAutoScroll_ItemsCollectionChanged(
            (LoggingListBox)d,
            (bool)e.NewValue);
    }
 
    /// <summary>
    /// Subscribes to the list items' collection changed event if AutoScroll is enabled.
    /// Otherwise, it unsubscribes from that event.
    /// For this to work, the underlying list must implement INotifyCollectionChanged.
    ///
    /// (This function was only creative for brevity)
    /// </summary>
    /// <param name="listBox">The list box containing the items collection.</param>
    /// <param name="subscribe">Subscribe to the collection changed event?</param>
    private static void SubscribeToAutoScroll_ItemsCollectionChanged(
        LoggingListBox listBox, bool subscribe)
    {
        INotifyCollectionChanged notifyCollection =
            listBox.Items.SourceCollection as INotifyCollectionChanged;
        if (notifyCollection != null)
        {
            if (subscribe)
            {
                //AutoScroll is turned on, subscribe to collection changed events.
                notifyCollection.CollectionChanged += 
                    listBox.AutoScroll_ItemsCollectionChanged;
            }
            else
            {
                //AutoScroll is turned off, unsubscribe from collection changed events.
                notifyCollection.CollectionChanged -= 
                    listBox.AutoScroll_ItemsCollectionChanged;
            }
        }
    }
 
    /// <summary>
    /// Event handler called only when the ItemCollection changes
    /// and if AutoScroll is enabled.
    /// </summary>
    /// <param name="sender">The ItemCollection.</param>
    /// <param name="e">Change event args.</param>
    private void AutoScroll_ItemsCollectionChanged(
        object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            int count = Items.Count;
            ScrollIntoView(Items[count - 1]);
        }
    }
 
    /// <summary>
    /// Constructor a new LoggingListBox.
    /// </summary>
    public LoggingListBox()
    {
        //Subscribe to the AutoScroll property's items collection 
        //changed handler by default if AutoScroll is enabled by default.
        SubscribeToAutoScroll_ItemsCollectionChanged(
            this, (bool)AutoScrollProperty.DefaultMetadata.DefaultValue);
    }
}


Et voici ce que j'ai déjà converti avec mes connaissances et l'utilisation de convertisseur en ligne:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Imports System.Collections.Specialized
 
Public Class LoggingListBox : Inherits ListBox
    Public Shared ReadOnly AutoScrollProperty As DependencyProperty = DependencyProperty.Register("AutoScroll", GetType(Boolean), GetType(LoggingListBox), New FrameworkPropertyMetadata(True, FrameworkPropertyMetadataOptions.AffectsArrange Or FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, AddressOf AutoScroll_PropertyChanged))
 
    '<Category("Common")>
    Public Property AutoScroll As Boolean
        Get
            Return CBool(GetValue(AutoScrollProperty))
        End Get
        Set(ByVal value As Boolean)
            SetValue(AutoScrollProperty, value)
        End Set
    End Property
 
    Private Shared Sub AutoScroll_PropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        SubscribeToAutoScroll_ItemsCollectionChanged(CType(d, LoggingListBox), CBool(e.NewValue))
    End Sub
 
    Private Shared Sub SubscribeToAutoScroll_ItemsCollectionChanged(ByVal listBox As LoggingListBox, ByVal subscribe As Boolean)
        Dim notifyCollection As INotifyCollectionChanged = TryCast(listBox.Items.SourceCollection, INotifyCollectionChanged)
 
        If notifyCollection IsNot Nothing Then
 
            If subscribe Then
                notifyCollection.CollectionChanged += AddressOf listBox.AutoScroll_ItemsCollectionChanged
            Else
                notifyCollection.CollectionChanged -= AddressOf listBox.AutoScroll_ItemsCollectionChanged
            End If
        End If
    End Sub
 
    Private Sub AutoScroll_ItemsCollectionChanged(ByVal sender As Object, ByVal e As NotifyCollectionChangedEventArgs)
        If e.Action = NotifyCollectionChangedAction.Add Then
            Dim count As Integer = Items.Count
            ScrollIntoView(Items(count - 1))
        End If
    End Sub
 
    Public Sub New()
        SubscribeToAutoScroll_ItemsCollectionChanged(Me, CBool(AutoScrollProperty.DefaultMetadata.DefaultValue))
    End Sub
 
End Class
J'ai une erreur sur l'instanciation des événements, il m'indique qu'il faut utiliser RaiseEvent, j'ai deja eue le cas donc:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
Private Shared Sub SubscribeToAutoScroll_ItemsCollectionChanged(ByVal listBox As LoggingListBox, ByVal subscribe As Boolean)
        Dim notifyCollection As INotifyCollectionChanged = TryCast(listBox.Items.SourceCollection, INotifyCollectionChanged)
 
        If notifyCollection IsNot Nothing Then
 
            If subscribe Then
                notifyCollection.CollectionChanged += AddressOf listBox.AutoScroll_ItemsCollectionChanged
            Else
                notifyCollection.CollectionChanged -= AddressOf listBox.AutoScroll_ItemsCollectionChanged
            End If
        End If
    End Sub

Voila ce que j'ai fait:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
RaiseEvent notifyCollection.CollectionChanged, AddressOf listBox.AutoScroll_ItemsCollectionChanged
Il me dit qu'il ne trouve pas notifyCollection alors qu'elle est déclarée juste au dessus. D’ailleurs il me rajoute automatiquement ()

Code : Sélectionner tout - Visualiser dans une fenêtre à part
RaiseEvent notifyCollection().CollectionChanged, AddressOf listBox.AutoScroll_ItemsCollectionChanged
Et puis je ne connais pas la fonction -= en C# pour la déclaration des événements je suppose que c'est justement pour supprimer l'enclenchement de l’événement, quelle serait l'équivalent en VB.

Merci de votre aide.