IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Presentation Foundation Discussion :

[WPF] Image ne se met pas à jour (INotifyPropertyChanged)


Sujet :

Windows Presentation Foundation

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 158
    Points : 41
    Points
    41
    Par défaut [WPF] Image ne se met pas à jour (INotifyPropertyChanged)
    Nom : Untitled-1.png
Affichages : 263
Taille : 14,7 Ko

    Bonjour,
    Dans cet exemple, l'utilisateur doit pouvoir remplacer l'image correspondant à l'item sélectionné (il s'agit donc bien d'un remplacement. L'image sera remplacée sur le disque..mais portera toujours le même nom - item1.jpg, item2.jpg,...)

    Si l'uri vers l'image est vide (comme c'est la cas pour l'item1 de l'exemple) cela se passe sans soucis.
    Si il y a déjà un uri et que je charge une nouvelle image, je peux vérifier que la nouvelle image a bien été copiée..et a remplacé la précédente...mais pourtant c'est toujours l'ancienne image qui s'affiche!

    Pourriez-vous m'aider svp? Qu'est ce que je fais de travers ;-) ?

    Code vb.net : 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
     
    <Window x:Class="MainWindow"
        xmlns:local="clr-namespace:WpfApplication1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
     
        <Grid>
            <Grid.Resources>
                <local:checkImageURL x:Key="checkImage"/>
            </Grid.Resources>
            <ListView Height="230" HorizontalAlignment="Left" Margin="12,12,0,0" Name="PersonListView" VerticalAlignment="Top" Width="445">
                <ListView.View>
                    <GridView >
                        <GridViewColumn DisplayMemberBinding="{Binding Id}" Width="80">
                            <GridViewColumnHeader>Id</GridViewColumnHeader>
                        </GridViewColumn>
                        <GridViewColumn DisplayMemberBinding="{Binding Name}" Width="100">
                            <GridViewColumnHeader>Name</GridViewColumnHeader>
                        </GridViewColumn>
                        <GridViewColumn Width="100">
                            <GridViewColumnHeader>Picture</GridViewColumnHeader>
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <Image Source="{Binding Path=Picture, Converter={StaticResource checkImage}}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>
            </ListView>
            <Button Content="Effacer image" Height="23" HorizontalAlignment="Right" Margin="0,263,192,0" Name="Button1" VerticalAlignment="Top" Width="112" />
            <Button Content="Remplacer image" Height="23" HorizontalAlignment="Right" Margin="0,263,46,0" Name="Button2" VerticalAlignment="Top" Width="112" />
        </Grid>
    </Window>

    Code vb.net : 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
    101
     
    Imports System.Collections.ObjectModel
    Imports System.ComponentModel
    Imports System.IO
     
    Class MainWindow
        Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
            Dim personList As New List(Of Person)()
            personList.Add(New Person() With {.Id = 1, .Name = "Item1", .Picture = ""})
            personList.Add(New Person() With {.Id = 2, .Name = "Item2", .Picture = "images\Item2.jpg"})
            personList.Add(New Person() With {.Id = 3, .Name = "Item3", .Picture = "images\Item3.jpg"})
            PersonListView.ItemsSource = personList
        End Sub
        Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
            Dim p As Person = TryCast(PersonListView.SelectedItem, Person)
            p.Picture = ""
        End Sub
        Private Sub Button2_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button2.Click
            Dim p As Person = TryCast(PersonListView.SelectedItem, Person)
            Dim dlg As New Microsoft.Win32.OpenFileDialog()
            dlg.Title = "Select image"
            dlg.Filter = "All Graphics Types|*.bmp;*.jpg;*.jpeg;*.png;*.tif;*.tiff|" + "BMP|*.bmp|GIF|*.gif|JPG|*.jpg;*.jpeg|PNG|*.png|TIFF|*.tif;*.tiff"
            ' Show open file dialog box
            Dim result? As Boolean = dlg.ShowDialog()
            ' Process open file dialog box results
            If result = True Then
                Dim filename As String = dlg.FileName
                If Path.GetExtension(filename).ToLower = ".jpg" Then
                    File.Copy(filename, String.Concat("images\", p.Name, ".jpg"), True)
                Else
                    Dim bitmap As New BitmapImage()
                    bitmap.BeginInit()
                    bitmap.UriSource = New Uri(filename)
                    bitmap.EndInit()
                    Dim encoder As JpegBitmapEncoder = New JpegBitmapEncoder()
                    encoder.Frames.Add(BitmapFrame.Create(DirectCast(bitmap, BitmapImage)))
                    Using filestream = New FileStream(String.Concat("images\", p.Name, ".jpg"), FileMode.Create)
                        encoder.Save(filestream)
                    End Using
                End If
                '
                p.Picture = String.Concat("images\", p.Name, ".jpg")
            End If
        End Sub
    End Class
    Public Class checkImageURL
        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
            If value = "" Then
                Return Nothing
            Else
                Dim fullPath As String = Path.GetFullPath(value)
                Dim btm As New BitmapImage()
                btm.BeginInit()
                btm.UriSource = New Uri(fullPath)
                btm.CacheOption = BitmapCacheOption.OnLoad
                btm.EndInit()
                Return btm
            End If
            Return Nothing
        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
            Return Nothing
        End Function
    End Class
    Public Class Person
        Implements INotifyPropertyChanged
        Public Property Id() As Int32
            Get
                Return m_Id
            End Get
            Set(value As Int32)
                m_Id = value
            End Set
        End Property
        Private m_Id As Int32
        Public Property Name() As String
            Get
                Return m_Name
            End Get
            Set(value As String)
                m_Name = value
            End Set
        End Property
        Private m_Name As String
        Public Property Picture() As String
            Get
                Return m_Picture
            End Get
            Set(value As String)
                m_Picture = value
                RaisePropertyChanged("Picture")
            End Set
        End Property
        Private m_Picture As String
        Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
        '
        Private Sub RaisePropertyChanged(ByVal propName As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
        End Sub
    End Class

  2. #2
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    rebonjour

    Probleme dans ton design....
    Quand aucune image n'est affecte la prop Picture passé de "" à la valeur chaine "images\", p.Name, ".jpg"
    et elle est mise à jour dans ton class Person ce qui declenche une Notification à l'UI...
    Qaund une image est deja affecte la prop Picture reste egale " à la valeur chaine "images\", p.Name, ".jpg" (puisque p.Name ne change pas)... Mr BINDING IGNORE TOUT meme si l'image a ete change reellement

    En consequence tu dois simuler ce changement pour Mr BINDING en mettant la prop Picture ="" et ensuite lui affecter la chaine initiale "images\", p.Name, ".jpg" ...
    code .vb à modifier :
    Code vb.net : 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
     
     
       Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button2.Click
            Dim p As Person = TryCast(PersonListView.SelectedItem, Person)
     
            '-------------------------------------------
            ' "images\", p.Name, ".jpg" cette valeur chaine de la prop Picture ne change pas meme si l'image 
            'ainsi designee a change(par ecrasement)
            'il faut alors reinitialiser la prop Picture pour simuler une notification de changement
            'de prop pour binding ........
            '
            If p.Picture <> "" Then 'lorsque l'uri ne change pas...
                p.Picture = "" ' changeons là
            End If
        '--------------------------------------------
     
            Dim dlg As New Microsoft.Win32.OpenFileDialog()
            dlg.Title = "Select image"
            dlg.Filter = "All Graphics Types|*.bmp;*.jpg;*.jpeg;*.png;*.tif;*.tiff|" + "BMP|*.bmp|GIF|*.gif|JPG|*.jpg;*.jpeg|PNG|*.png|TIFF|*.tif;*.tiff"
            ' Show open file dialog box
            Dim result? As Boolean = dlg.ShowDialog()
            ' Process open file dialog box results
            If result = True Then
                Dim filename As String = dlg.FileName
                If Path.GetExtension(filename).ToLower = ".jpg" Then
                    File.Copy(filename, String.Concat("images\", p.Name, ".jpg"), True)
                Else
                    Dim bitmap As New BitmapImage()
                    bitmap.BeginInit()
                    bitmap.UriSource = New Uri(filename)
                    bitmap.EndInit()
                    Dim encoder As JpegBitmapEncoder = New JpegBitmapEncoder()
                    encoder.Frames.Add(BitmapFrame.Create(DirectCast(bitmap, BitmapImage)))
                    Using filestream = New FileStream(String.Concat("images\", p.Name, ".jpg"), FileMode.Create)
                        encoder.Save(filestream)
                    End Using
                End If
                '
     
     
            End If
            p.Picture = String.Concat("images\", p.Name, ".jpg")
     
        End Sub
    BON CODE.........

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 158
    Points : 41
    Points
    41
    Par défaut
    MABROUKI,

    Merci à nouveau pour ta réponse!
    J'avais en effet pensé à cela dans un des test que j'avais fait...en mettant l'une après l'autre les lignes suivantes pour forcer le refresh

    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    '...chargement physique d'une image
    p.Picture = ""
    p.Picture = String.Concat("images\", p.Name, ".jpg")

    ...mais cela ne marchait pas!

    Je vois que toi tu effaces le lien puis lance l'update de l'image PUIS redonne un lien
    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    p.Picture = ""
    '...chargement physique d'une image
    p.Picture = String.Concat("images\", p.Name, ".jpg")

    Je ne vois pas beaucoup de différence, à part du temps qui s'est passé!? Si tu peux m'expliquer!?

    Entre-temps, j'ai continué "d'enquêter" en essayant de comprendre pourquoi, alors que l'image avait physiquement changé, l'application continuait à afficher "l'ancienne" image..comme si elle était en 'cache'. Et c'est cette notion de cache qui m'a permis de découvrir ceci, que je te livre. Je ne touche donc à rien au code soumis en premier, j'ajoute juste BitmapCreateOptions.IgnoreImageCache et cela fonctionne comme attendu!!

    Donc, apparemment, redonner une valeur (même la même!) a un URI bindé va bel et bien déclencher une action...si ce n'est que dans le cas d'une même valeur le système utilise celle en cache!! (jusqu'à ce qu'on utilise IgnoreImageCache)

    Code vb.net : 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
    Public Class checkImageURL
        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
            If value = "" Then
                Return Nothing
            Else
                Dim fullPath As String = Path.GetFullPath(value)
                Dim btm As New BitmapImage()
                btm.BeginInit()
                btm.CacheOption = BitmapCacheOption.OnLoad
                btm.CreateOptions = BitmapCreateOptions.IgnoreImageCache
                btm.UriSource = New Uri(fullPath)
                btm.EndInit()
                Return btm
            End If
            Return Nothing
        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
            Return Nothing
        End Function
    End Class

  4. #4
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    bonjour
    La difference fondamentale entre ton code et le mien c'est le If que tu n'as pas note....Il a pour but simplement d'operer comme dans le cas d'une image non affecte....!!!
    bon code....

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/10/2006, 08h24
  2. Combobox.text qui ne se met pas à jour
    Par davels dans le forum Delphi
    Réponses: 6
    Dernier message: 21/08/2006, 10h29
  3. [AJAX] XMLHTTPREQUEST ne se met pas à jour :-/
    Par franckarts dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 04/08/2006, 18h11
  4. Update Récalcitrante !! Ne met pas à jour !
    Par samlepiratepaddy dans le forum Access
    Réponses: 14
    Dernier message: 28/10/2005, 09h31
  5. un update qui ne met pas à jour
    Par dor_boucle dans le forum Requêtes
    Réponses: 3
    Dernier message: 14/10/2005, 09h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo