2008-08-21 18 views
57

J'essaie de lier une liste d'objets personnalisés à une image WPF comme ceci:image UriSource et la liaison de données

<Image> 
    <Image.Source> 
     <BitmapImage UriSource="{Binding Path=ImagePath}" /> 
    </Image.Source> 
</Image> 

Mais cela ne fonctionne pas. C'est l'erreur que j'obtiens:

"La propriété 'UriSource' ou la propriété 'StreamSource' doit être définie."

Que manque-t-il?

Répondre

74

WPF dispose de convertisseurs intégrés pour certains types. Si vous liez la propriété Source de l'image à une valeur string ou Uri, sous le capot WPF utilisera un ImageSourceConverter pour convertir la valeur en ImageSource.

Alors

<Image Source="{Binding ImageSource}"/> 

fonctionnerait si la propriété était ImageSource une représentation de chaîne d'un URI valide à une image.

Vous pouvez bien sûr rouler votre propre convertisseur de reliure:

public class ImageConverter : IValueConverter 
{ 
    public object Convert(
     object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return new BitmapImage(new Uri(value.ToString())); 
    } 

    public object ConvertBack(
     object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

et l'utiliser comme ceci:

<Image Source="{Binding ImageSource, Converter={StaticResource ImageConverter}}"/> 
+4

(En fait, le convertisseur de type ne crée pas 'BitmapImage', mais une autre sous-classe de' ImageSource': 'BitmapFrameDecode', qui est interne.) –

+0

@ H.B. Comment vous convertir si vous vouliez persister le changement de l'image? – Igor

+0

Alternative à un convertisseur: Faites votre propriété à laquelle vous liez (ici: 'ImageSource') de type' Uri' ou 'BitmapImage' et cast là. Si vous avez besoin de traiter les valeurs possibles de 'null' (cast a échoué etc.) ajoutez' TargetNullValue = {x: Null} 'à votre liaison. – Gerrit

9

Vous devez disposer d'une implémentation de l'interface IValueConverter qui convertit l'uri en une image. Votre mise en œuvre Convertir de IValueConverter ressemblera à quelque chose comme ceci:

BitmapImage image = new BitmapImage(); 
image.BeginInit(); 
image.UriSource = new Uri(value as string); 
image.EndInit(); 

return image; 

Ensuite, vous aurez besoin d'utiliser le convertisseur dans votre reliure:

<Image> 
    <Image.Source> 
     <BitmapImage UriSource="{Binding Path=ImagePath, Converter=...}" /> 
    </Image.Source> 
</Image> 
19

Vous pouvez aussi simplement définir l'attribut source plutôt que d'utiliser l'enfant éléments. Pour ce faire, votre classe doit renvoyer l'image en tant qu'image bitmap. Voici un exemple d'une façon dont je l'ai fait

<Image Width="90" Height="90" 
     Source="{Binding Path=ImageSource}" 
     Margin="0,0,0,5" /> 

Et la propriété de classe est simplement ce

public object ImageSource { 
    get { 
     BitmapImage image = new BitmapImage(); 

     try { 
      image.BeginInit(); 
      image.CacheOption = BitmapCacheOption.OnLoad; 
      image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; 
      image.UriSource = new Uri(FullPath, UriKind.Absolute); 
      image.EndInit(); 
     } 
     catch{ 
      return DependencyProperty.UnsetValue; 
     } 

     return image; 
    } 
} 

Je suppose que ce peut être un peu plus de travail que le convertisseur de valeur, mais il est une autre option.

+1

Une implémentation similaire à c'est parfait pour quand votre ressource bitmap est déjà chargé dans votre objet et vous voulez passer les bits à la liaison. MERCI! –

23

This article par Atul Gupta a exemple de code qui couvre plusieurs scénarios:

  1. Liaison d'image de ressource régulière à la propriété Source dans XAML
  2. Liaison d'une image de ressource, mais à partir du code suivant
  3. Liaison d'une image de ressource dans le code en utilisant Application.GetResourceStream
  4. image Chargement du chemin du fichier flux de mémoire (en est de même lorsque le chargement de données d'images de blog de base de données)
  5. image Chargement du chemin du fichier, mais en utilisant la liaison à un chemin de fichier propriété
  6. données d'image liant à un contrôle utilisateur qui a en interne le contrôle de l'image via la propriété de dépendance
  7. Identique au point 5, mais aussi veiller à ce que le fichier ne se est verrouillé pas sur le disque dur
6

le problème avec la réponse qui a été choisie ici est que lors de la navigation d'avant en arrière, le convertisseur aura déclenché à chaque fois que la page est affichée.

Cela provoque la création de nouveaux handles de fichiers en continu et bloque toute tentative de suppression du fichier car il est toujours utilisé. Cela peut être vérifié en utilisant Process Explorer.

Si le fichier image peut être supprimée à un moment donné, un convertisseur comme celui-ci pourrait être utilisé: using XAML to bind to a System.Drawing.Image into a System.Windows.Image control

L'inconvénient de cette méthode de flux de mémoire est que l'image (s) se charge et décodé à chaque fois "Pour éviter que les images ne soient décodées plus d'une fois, affectez la propriété Image.Source à un Uri au lieu d'utiliser des flux mémoire" Source: "Conseils de performance pour les applications Windows Store utilisant XAML"

Pour résoudre le problème de performances, le modèle de référentiel peut être utilisé pour fournir une couche de mise en cache. La mise en cache peut avoir lieu en mémoire, ce qui peut provoquer des problèmes de mémoire, ou en tant que fichiers miniatures résidant dans un dossier temporaire et pouvant être effacés à la fermeture de l'application.

4

vous pouvez utiliser

classe ImageSourceConverter

pour obtenir ce que vous voulez

img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png"); 
Questions connexes