Jayme65
Messages postés60Date d'inscriptionlundi 23 avril 2007StatutMembreDernière intervention26 mars 2019
-
17 oct. 2016 à 18:17
Jayme65
Messages postés60Date d'inscriptionlundi 23 avril 2007StatutMembreDernière intervention26 mars 2019
-
18 oct. 2016 à 10:26
Bonjour,
J'ai un "carrousel" constitué de ContentControls avec une animation des éléments dans le déplacement.
Lorsque l'on descend (Flèche 'Bas' sur le clavier), un nouveau ContentControl (caché hors de la grille dans un premier temps) est créé en bas et ensuite animé..et à l'inverse, au dessus, celui qui est alors masqué est supprimé!
Avec la flèche gauche/droite du clavier on remonte/descend d'une page complète!
En inspectant l'utilisation de la mémoire je me suis rendu compte que la mémoire n'est pas libérée lorsque je descend 1 par 1.
Les 'anciens' ContentControl sont bien effacés au fur et à mesure de la grille (et d'un dictionnaire qui contient les éléments disponibles)..mais la mémoire n'est pas libérée.
Elle l'est par contre quand on remonte/descend d'une page (il faut dire qu'il y a alors un reset des enfants de la grille et du dictionnaire)
Imports System.IO
Imports System.Windows.Media.Animation
Class MainWindow
Dim personDB As New List(Of Person)
Dim listDictionary As Dictionary(Of Integer, ContentControl)
Dim masterIndex As Integer = 0
Dim delay As Double = 0.2
' ***** List settings *****
Dim ListItemsNumber As Integer = 4 ' Number of items up and down the focused item
Dim FocusedItemCoeff As Double = 2.5 ' Scale ration for focused item
Dim ItemHeight As Integer ' Height for a non-focused item
Dim ItemCoordinates(ListItemsNumber * 2 + 3) As Integer
'
Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
SetCoordinates()
SetPersons()
CreateList(masterIndex)
End Sub
Sub SetCoordinates()
ItemHeight = Math.Floor(ListGrid.ActualHeight / (ListItemsNumber * 2 + FocusedItemCoeff))
' Top hidden Item
ItemCoordinates(0) = ItemHeight * -1
' Top Items
For up As Integer = 1 To ListItemsNumber
ItemCoordinates(up) = ItemHeight * (up - 1)
Next
' Center Item
ItemCoordinates(ListItemsNumber + 1) = ItemHeight * ListItemsNumber
' Bottom items
For down As Integer = 1 To ListItemsNumber
ItemCoordinates(ListItemsNumber + 1 + down) = Math.Floor(ItemHeight * ((down - 1) + FocusedItemCoeff + ListItemsNumber))
Next
' Bottom hidden Item
ItemCoordinates(ListItemsNumber * 2 + 2) = Math.Floor(ItemHeight * (ListItemsNumber * 2 + FocusedItemCoeff))
End Sub
Sub SetPersons()
For i As Integer = 1 To 200
personDB.Add(New Person() With {.lastName = "LastName" & i.ToString, .imageUrl = "01.jpg"})
Next
End Sub
Sub CreateList(focusedIndex As Integer)
' Clear grid and dictionary
ListGrid.Children.Clear()
listDictionary = New Dictionary(Of Integer, ContentControl)
' Top Items
For up As Integer = 1 To ListItemsNumber
If (focusedIndex - up > -1) Then
Dim cc As New ContentControl
cc.ContentTemplate = DirectCast(Me.Resources("ccImage"), DataTemplate)
cc.Height = ItemHeight
cc.Width = 200
cc.VerticalAlignment = Windows.VerticalAlignment.Top
cc.Margin = New Thickness(0, ItemCoordinates(ListItemsNumber + 1 - up), 0, 0)
cc.Content = New Displayed With {.lastName = personDB(focusedIndex - up).lastName, .imageUrl = personDB(focusedIndex - up).imageUrl}
listDictionary.Add(focusedIndex - up, cc)
ListGrid.Children.Add(cc)
End If
Next
' Center Item
If personDB.Count >= 0 Then
Dim cc As New ContentControl
cc.ContentTemplate = DirectCast(Me.Resources("ccImage"), DataTemplate)
cc.Height = Math.Floor(ItemHeight * FocusedItemCoeff)
cc.Width = 300
cc.VerticalAlignment = Windows.VerticalAlignment.Top
cc.Margin = New Thickness(0, ItemCoordinates(ListItemsNumber + 1), 0, 0)
Dim dp As Displayed = New Displayed With {.lastName = personDB(focusedIndex).lastName, .imageUrl = personDB(focusedIndex).imageUrl}
cc.Content = dp
listDictionary.Add(focusedIndex, cc)
ListGrid.Children.Add(cc)
End If
' Bottom Items
For down As Integer = 1 To ListItemsNumber
If (focusedIndex + down <= personDB.Count - 1) Then
Dim cc As New ContentControl
cc.ContentTemplate = DirectCast(Me.Resources("ccImage"), DataTemplate)
cc.Height = ItemHeight
cc.Width = 200
cc.VerticalAlignment = Windows.VerticalAlignment.Top
cc.Margin = New Thickness(0, ItemCoordinates(ListItemsNumber + 1 + down), 0, 0)
Dim dp As Displayed = New Displayed With {.lastName = personDB(focusedIndex + down).lastName, .imageUrl = personDB(focusedIndex + down).imageUrl}
cc.Content = dp
listDictionary.Add(focusedIndex + down, cc)
ListGrid.Children.Add(cc)
End If
Next
End Sub
Private Sub MainWindow_KeyDown(ByVal sender As Object, ByVal keyData As System.Windows.Input.KeyEventArgs) Handles Me.KeyDown
If keyData.Key = Key.Down Then
If masterIndex < personDB.Count - 1 Then
GoDown()
End If
ElseIf keyData.Key = Key.Left Then
If masterIndex > 0 Then
If (masterIndex >= ListItemsNumber * 2 + 1) Then
masterIndex -= ListItemsNumber * 2 + 1
Else
masterIndex = 0
End If
CreateList(masterIndex)
End If
ElseIf keyData.Key = Key.Right Then
If masterIndex < personDB.Count - 1 Then
If (masterIndex + (ListItemsNumber * 2 + 1) <= personDB.Count - 1) Then
masterIndex += ListItemsNumber * 2 + 1
Else
masterIndex = personDB.Count - 1
End If
CreateList(masterIndex)
End If
End If
End Sub
Sub GoDown()
' Remove Top Hidden Item
If listDictionary.ContainsKey(masterIndex - ListItemsNumber - 1) Then
ListGrid.Children.Remove(listDictionary(masterIndex - ListItemsNumber - 1))
listDictionary.Remove(masterIndex - ListItemsNumber - 1)
End If
' Add new item at bottom
If masterIndex + ListItemsNumber + 1 <= personDB.Count - 1 Then
Dim cc As New ContentControl
cc.ContentTemplate = DirectCast(Me.Resources("ccImage"), DataTemplate)
cc.Height = ItemHeight
cc.Width = 200
cc.VerticalAlignment = Windows.VerticalAlignment.Top
cc.Margin = New Thickness(0, ItemCoordinates(ListItemsNumber * 2 + 2), 0, 0)
Dim dp As Displayed = New Displayed With {.lastName = personDB(masterIndex + ListItemsNumber + 1).lastName, .imageUrl = personDB(masterIndex + ListItemsNumber + 1).imageUrl}
cc.Content = dp
listDictionary.Add(masterIndex + ListItemsNumber + 1, cc)
ListGrid.Children.Add(cc)
End If
'
Dim myStoryboard As New Storyboard()
'
' Top animation
For up As Integer = 1 To ListItemsNumber
If (masterIndex - up > -1) Then
'Animating Margins
Dim myDoubleAnimation As New ThicknessAnimation()
Dim marginThickness As Thickness = listDictionary(masterIndex - up).Margin
Dim NewmarginThickness As Thickness = New Thickness(0, ItemCoordinates(ListItemsNumber - up), 0, 0)
myDoubleAnimation.From = marginThickness
myDoubleAnimation.To = NewmarginThickness
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(delay))
'myDoubleAnimation.EasingFunction = ease
Storyboard.SetTarget(myDoubleAnimation, listDictionary(masterIndex - up))
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Grid.MarginProperty))
myStoryboard.Children.Add(myDoubleAnimation)
End If
Next
' Center animation
If personDB.Count >= 0 Then
If (masterIndex < personDB.Count - 1) Then
'Animating Margins
Dim myDoubleAnimation As New ThicknessAnimation()
Dim marginThickness As Thickness = listDictionary(masterIndex).Margin
Dim NewmarginThickness As Thickness = New Thickness(0, ItemCoordinates(ListItemsNumber), 0, 0)
myDoubleAnimation.From = marginThickness
myDoubleAnimation.To = NewmarginThickness
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(delay))
Storyboard.SetTarget(myDoubleAnimation, listDictionary(masterIndex))
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Grid.MarginProperty))
myStoryboard.Children.Add(myDoubleAnimation)
'Animating Height
Dim myDoubleAnimation2 As New DoubleAnimation()
Dim prevHeight As Integer = listDictionary(masterIndex).Height
Dim newHeight As Integer = ItemHeight
myDoubleAnimation2.From = prevHeight
myDoubleAnimation2.To = newHeight
myDoubleAnimation2.Duration = New Duration(TimeSpan.FromSeconds(delay))
Storyboard.SetTarget(myDoubleAnimation2, listDictionary(masterIndex))
Storyboard.SetTargetProperty(myDoubleAnimation2, New PropertyPath(Grid.HeightProperty))
myStoryboard.Children.Add(myDoubleAnimation2)
'Animating Width
Dim myDoubleAnimation3 As New DoubleAnimation()
Dim prevWidth As Integer = listDictionary(masterIndex).Width
Dim newWidth As Integer = 200
myDoubleAnimation3.From = prevWidth
myDoubleAnimation3.To = newWidth
myDoubleAnimation3.Duration = New Duration(TimeSpan.FromSeconds(delay))
Storyboard.SetTarget(myDoubleAnimation3, listDictionary(masterIndex))
Storyboard.SetTargetProperty(myDoubleAnimation3, New PropertyPath(Grid.WidthProperty))
myStoryboard.Children.Add(myDoubleAnimation3)
End If
End If
' Bottom animation
If (masterIndex + 1 <= personDB.Count - 1) Then
'Animating Height
Dim myDoubleAnimation2 As New DoubleAnimation()
Dim prevHeight As Integer = listDictionary(masterIndex + 1).Height
Dim newHeight As Integer = Math.Floor(ItemHeight * FocusedItemCoeff)
myDoubleAnimation2.From = prevHeight
myDoubleAnimation2.To = newHeight
myDoubleAnimation2.Duration = New Duration(TimeSpan.FromSeconds(delay))
Storyboard.SetTarget(myDoubleAnimation2, listDictionary(masterIndex + 1))
Storyboard.SetTargetProperty(myDoubleAnimation2, New PropertyPath(Grid.HeightProperty))
myStoryboard.Children.Add(myDoubleAnimation2)
'Animating Width
Dim myDoubleAnimation3 As New DoubleAnimation()
Dim prevWidth As Integer = listDictionary(masterIndex + 1).Width
Dim newWidth As Integer = 300
myDoubleAnimation3.From = prevWidth
myDoubleAnimation3.To = newWidth
myDoubleAnimation3.Duration = New Duration(TimeSpan.FromSeconds(delay))
Storyboard.SetTarget(myDoubleAnimation3, listDictionary(masterIndex + 1))
Storyboard.SetTargetProperty(myDoubleAnimation3, New PropertyPath(Grid.WidthProperty))
myStoryboard.Children.Add(myDoubleAnimation3)
End If
For down As Integer = 1 To ListItemsNumber + 1
If (masterIndex + down <= personDB.Count - 1) Then
'Animating Margins
Dim myDoubleAnimation As New ThicknessAnimation()
Dim marginThickness As Thickness = listDictionary(masterIndex + down).Margin
Dim NewmarginThickness As Thickness = New Thickness(0, ItemCoordinates(ListItemsNumber + down), 0, 0)
myDoubleAnimation.From = marginThickness
myDoubleAnimation.To = NewmarginThickness
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(delay))
Storyboard.SetTarget(myDoubleAnimation, listDictionary(masterIndex + down))
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Grid.MarginProperty))
myStoryboard.Children.Add(myDoubleAnimation)
End If
Next
myStoryboard.Begin()
'
masterIndex += 1
End Sub
End Class
Public Class Person
Public Shared ReadOnly DescriptComparer As New DescriptComparerClass
Public lastName As String
Public imageUrl As String
Sub New()
End Sub
Public Class DescriptComparerClass
Implements IComparer(Of Person)
Public Function Compare(ByVal x As Person, ByVal y As Person) As Integer Implements System.Collections.Generic.IComparer(Of Person).Compare
Return String.Compare(x.lastName, y.lastName, True)
End Function
End Class
End Class
Public Class Displayed
Public _lastname As String
Public _imageUrl As String
Public Property lastName() As String
Get
Return _lastname
End Get
Set(value As String)
_lastname = value
End Set
End Property
Public Property imageUrl() As String
Get
Return _imageUrl
End Get
Set(value As String)
_imageUrl = value
End Set
End Property
Sub New()
End Sub
End Class
Public Class ImagePathConverter
Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
Dim relative As [String] = TryCast(value, String)
If String.IsNullOrEmpty(relative) Then
Return Nothing
End If
Return System.AppDomain.CurrentDomain.BaseDirectory & "Images\" & relative
End Function
Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
Throw New NotImplementedException()
End Function
End Class
Sub GoDown()
' Remove Top Hidden Item
If listDictionary.ContainsKey(masterIndex - ListItemsNumber - 1) Then
ListGrid.Children.Remove(listDictionary(masterIndex - ListItemsNumber - 1))
listDictionary.Remove(masterIndex - ListItemsNumber - 1)
End If
...le ContentControl enlevé de la grille semble toujours être existant "quelque part" ;-) car la mémoire grossit de plus en plus lors du défilement vers le bas (sur l'exemple joint, j'arrive à 500Mo sur une liste de 200 objets)
J'espère que je suis assez clair dans mes explications et que vous voudrez bien m'aider! Merci
NB: pour que le code marche, il faut créer un dossier 'Images' avec un fichier '01.jpg' à l'intérieur, au niveau de l'application.
On se déplace avec les flèches 'bas, gauche, droite'
Whismeril
Messages postés19027Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention24 avril 2024656 18 oct. 2016 à 09:40
Bonjour, il faut prendre en compte la façon dont c'est placé en mémoire.
Une collection (tableau, liste, dictionnaire etc..) c'est un espace où tu vas stocker les adresses de tes objets. Quand tu ajoutes un item, si cet item n'existe pas et que tu fais un Add de New toto, dans la mémoire il se passe deux choses différentes, d'abord ça crée un nouvel item quelque par, puis ça mets l'adresse de ce nouvel item dans la collection. Quand tu retires un item de la collection, ça e fait que retirer l'adresse de la collection.
Ça n'est pas parce que je retire un objet d'une collection qu'il n'est pas encore utiliser par ailleurs.
Ensuite intervient le garbage collector, son rôle est de nettoyer la mémoire inutile, la première chose à savoir est qu'il intervient quand il veut, même quand tu lui dit expressément qu'il faut y penser. Ensuite il commence par nettoyer les espaces qui sont clairement laisser à l'abandon, c'est à dire que tu as écrit dans le code que tu les "disposes" (voir l'interface IDisposable), après seulement il cherche les objets orphelins, c'est à dire ceux qui ne sont pas disposés mais dont il ne subsiste pas d'adresse stocké quelque part.
Donc si tu charges trop la ram, pour forcer un peu les choses, tu disposes tes objets (tu implémentés idisposable si nécessaire) et tu "forces" le garbage collector. Le Net est plein d'exemples pour les 2.
Cherches aussi en c#, et traduis le code en ligne, y a plusieurs sites dédiés
Jayme65
Messages postés60Date d'inscriptionlundi 23 avril 2007StatutMembreDernière intervention26 mars 20192 18 oct. 2016 à 09:50
Merci pour ta réponse globale! Je n'ai pas ces problèmes exposés!
Je pense maintenant que le problème doit être lié au Binding dans le XAML..car si je compose les ContentsControls par le code le problème de mémoire disparait
Sub GoDown()
...
' Add new item at bottom
If masterIndex + ListItemsNumber + 1 <= personDB.Count - 1 Then
Dim img As New Image
Dim bmp As New BitmapImage()
bmp = New BitmapImage(New Uri(System.AppDomain.CurrentDomain.BaseDirectory & "Images\" & personDB(masterIndex + ListItemsNumber + 1).imageUrl))
img.Source = bmp
Dim cc As New ContentControl
cc.Height = ItemHeight
cc.Width = 200
cc.VerticalAlignment = Windows.VerticalAlignment.Top
cc.Margin = New Thickness(0, ItemCoordinates(ListItemsNumber * 2 + 2), 0, 0)
cc.Content = img
listDictionary.Add(masterIndex + ListItemsNumber + 1, cc)
ListGrid.Children.Add(cc)
End If
SI le code est adapté de cette façon pour ne plus aller chercher son ContentTemplate dans le XAML...plus de problèmes avec la mémoire!
Avez-vous une idéé de pourquoi cela arrive si j'utilise plutôt la version XAML de la chose?
Merci!!