2008-08-21 15 views
57

Estoy tratando de enlazar una lista de objetos personalizados a una imagen de WPF como esto:imagen UriSource y enlace de datos

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

Pero no funciona. Este es el error que obtengo:

"Se debe establecer la propiedad 'UriSource' o la propiedad 'StreamSource'."

¿Qué me falta?

Respuesta

74

WPF tiene convertidores incorporados para ciertos tipos. Si vincula la propiedad de la Imagen Source a un valor de string o Uri, bajo el capó WPF utilizará un ImageSourceConverter para convertir el valor a ImageSource.

Así

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

funcionaría si la propiedad ImageSource era una representación de cadena de un URI válido a una imagen.

Por supuesto, puede rodar su propio conversor Encuadernación:

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(); 
    } 
} 

y utilizar de esta manera:

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

(En realidad, el convertidor de tipos no crea una 'BitmapImage', sino otra subclase de' ImageSource': 'BitmapFrameDecode', que es interna.) –

+0

@ H.B. ¿Cómo volverías a convertirte si quisieras conservar el cambio de imagen? – Igor

+0

Alternativa a un convertidor: Haga que su propiedad se vincule (aquí: 'ImageSource') de tipo' Uri' o 'BitmapImage' y envíe allí. Si necesita tratar con posibles valores 'null' (error de conversión, etc.) agregue' TargetNullValue = {x: Null} 'a su enlace. – Gerrit

9

Necesita tener una implementación de la interfaz IValueConverter que convierta el uri en una imagen. Su aplicación Convert de IValueConverter se verá algo como esto:

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

return image; 

, entonces tendrá que utilizar el convertidor en su unión:

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

También puede establecer simplemente el atributo de origen en lugar de utilizar el niño elementos. Para hacer esto, su clase necesita devolver la imagen como una Imagen de Mapa de bits. Aquí está un ejemplo de una forma que lo he hecho

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

Y la propiedad de clase es simplemente esto

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; 
    } 
} 

supongo que puede ser un poco más trabajo que el convertidor de valores, pero es otra opción.

+1

Una aplicación similar a esto es perfecto para cuando el recurso de mapa de bits ya está cargado en su objetivo y quieres pasar los bits a la encuadernación. ¡GRACIAS! –

23

This article por Atul Gupta tiene código de ejemplo que abarca varios escenarios:

  1. Enlace de imagen de recurso normal a la propiedad Origen en XAML
  2. Imagen de recurso de enlace, pero desde el código detrás de
  3. Imagen de recurso de enlace en el código subyacente mediante la aplicación.GetResourceStream
  4. Cargando imagen a partir de la ruta del archivo a través de secuencia de memoria (lo mismo es aplicable al cargar los datos de imagen del blog de la base de datos) Imagen
  5. Carga de la ruta del archivo, pero mediante el uso de la unión a una ruta de archivo de la propiedad
  6. datos de imagen unión a una control de usuario que tiene internamente control de la imagen a través de propiedad de dependencia
  7. Igual que el punto 5, sino también asegurar que el archivo no de obtener bloqueado en el disco duro
6

el problema con la respuesta que se ha elegido aquí es que al navegar de ida y vuelta, el convertidor obtendrá activado cada vez que se muestra la página.

Esto provoca que se creen continuamente nuevos identificadores de archivo y bloqueará cualquier intento de eliminar el archivo porque todavía está en uso. Esto se puede verificar usando Process Explorer.

Si el archivo de imagen puede ser eliminado en algún momento, un convertidor como este podría usarse: using XAML to bind to a System.Drawing.Image into a System.Windows.Image control

La desventaja de este método de secuencia de memoria es que la imagen (s) se cargan y se decodifica cada vez y no se puede almacenar en caché: "Para evitar que las imágenes se decodifiquen más de una vez, asigne la propiedad Image.Source de un Uri en lugar de usar secuencias de memoria" Fuente: "Sugerencias de rendimiento para Windows Store usando XAML"

Para resolver el problema de rendimiento, el patrón de repositorio se puede usar para proporcionar una capa de almacenamiento en caché. El almacenamiento en caché puede tener lugar en la memoria, lo que puede causar problemas de memoria, o como archivos en miniatura que residen en una carpeta temporal que se puede borrar cuando la aplicación se cierra.

4

puede usar

clase ImageSourceConverter

para conseguir lo que quiere

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