2010-04-04 225 views
8

我有下面XAML代码:绑定Image.Source到WPF中的字符串?

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}" 
    WindowStartupLocation="CenterScreen" 
    Title="Window1" Height="300" Width="300"> 

    <Grid> 
     <Image x:Name="TestImage" Source="{Binding Path=ImageSource}" /> 
    </Grid> 

</Window> 

而且,存在使影像从Base64串的方法,包括:

Image Base64StringToImage(string base64ImageString) 
{ 
    try 
    { 
     byte[] b; 
     b = Convert.FromBase64String(base64ImageString); 
     MemoryStream ms = new System.IO.MemoryStream(b); 
     System.Drawing.Image img = System.Drawing.Image.FromStream(ms); 

     ////////////////////////////////////////////// 
     //convert System.Drawing.Image to WPF image 
     System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(img); 
     IntPtr hBitmap = bmp.GetHbitmap(); 
     System.Windows.Media.ImageSource imageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 

     Image wpfImage = new Image(); 
     wpfImage.Source = imageSource; 
     wpfImage.Width = wpfImage.Height = 16; 
     ////////////////////////////////////////////// 

     return wpfImage; 
    } 
    catch 
    { 
     Image img1 = new Image(); 
     img1.Source = new BitmapImage(new Uri(@"/passwordManager;component/images/TreeView/empty-bookmark.png", UriKind.Relative)); 
     img1.Width = img1.Height = 16; 
     return img1; 
    } 
} 

现在,我要绑定到TestImageBase64StringToImage输出方法。
我用下面的方法:

public string ImageSource { get; set; } 
ImageSource = Base64StringToImage("iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABjUExURXK45////6fT8PX6/bTZ8onE643F7Pf7/pDH7PP5/dns+b7e9MPh9Xq86NHo947G7Hm76NTp+PL4/bHY8ojD67rc85bK7b3e9MTh9dLo97vd8/D3/Hy96Xe76Nfr+H+/6f///1bvXooAAAAhdFJOU///////////////////////////////////////////AJ/B0CEAAACHSURBVHjaXI/ZFoMgEEMzLCqg1q37Yv//KxvAlh7zMuQeyAS8d8I2z8PT/AMDShWQfCYJHL0FmlcXSQTGi7NNLSMwR2BQaXE1IfAguPFx5UQmeqwEHSfviz7w0BIMyU86khBDZ8DLfWHOGPJahe66MKe/fIupXKst1VXxW/VgT/3utz99BBgA4P0So6hyl+QAAAAASUVORK5CYIII").Source.ToString(); 

,但没有发生。
我该如何解决它?

顺便说一句,我已经死了确认的base64字符串正确

+0

不相关的问题,但你尝试加载与'变种IMG =新的BitmapImage形象{StreamSource = ms}'? – 2010-04-04 08:50:24

+0

@Simon:不,我没有。但是,为什么我这样做? – 2010-04-04 09:39:23

+3

那么,你可以直接使用WPF加载图像,而不是通过GDI +(System.Drawing)。因为它意味着从XAML中使用,所以你实际上必须做'var source = new BitmapImage(); source.BeginInit(); source.StreamSource = ms; source.EndInit()'。 – 2010-04-04 09:50:51

回答

14

为补充@ itowlson出色的答案,这是你的代码应该是什么样子:

// MainWindow.xaml 
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <DockPanel> 
     <Image Source="{Binding ImageSource}" /> 
    </DockPanel> 
</Window> 

// MainWindow.xaml.cs 
using System.ComponentModel; 
using System.IO; 
using System.Windows; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     var model = new MainModel(); 
     DataContext = model; 

     model.SetImageData(File.ReadAllBytes(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg")); 
    } 
} 

class MainModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public void SetImageData(byte[] data) { 
     var source = new BitmapImage(); 
     source.BeginInit(); 
     source.StreamSource = new MemoryStream(data); 
     source.EndInit(); 

     // use public setter 
     ImageSource = source; 
    } 

    ImageSource imageSource; 
    public ImageSource ImageSource 
    { 
     get { return imageSource; } 
     set 
     { 
      imageSource = value; 
      OnPropertyChanged("ImageSource"); 
     } 
    } 

    protected void OnPropertyChanged(string name) 
    { 
     var handler = PropertyChanged; 
     if (null != handler) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 
+0

谢谢,我已经完成了,但没有任何显示。只是显示一个字符串而不是image =>'WpfApplication1.MainModel'。你可以从http://www.mediafire.com/?nze3qjmzjtm下载我的项目。 – 2010-04-04 11:20:57

+0

差不多,它是'DataContext = model;',而不是'Content = model;'。此外,您可以直接在'SetImageData()'中使用'Convert.FromBase64String(...)','BitmapImage'可以加载与'System.Drawing.Image'相同的图像。 – 2010-04-04 14:09:56

+0

非常感谢bro,我真的需要它。谢谢 :-) – 2010-04-04 14:25:57

22

让我们打破自己在做什么。

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

为此,绑定源需要是ImageSource或表示图像文件URI的字符串。那么让我们来看看ImageSource属性的实际内容。

public string ImageSource { get; set; } 

这里的一个问题是ImageSource不会引发PropertyChanged事件。因此,当您更新属性时,WPF不会更新绑定目标。

但是,ImageSource不是ImageSource,它是一个字符串。没关系,但是WPF会将该字符串解释为URI。什么是URI?

ImageSource = Base64StringToImage(BIG_HONKING_STRING).Source.ToString(); 

这是你的问题的要点。 ImageSource字符串实际上并不是一个URI,因为您的图像不是可寻址的资源。 Base64StringToImage从base64字符串中创建一个内存中的ImageSource,然后返回一个Image作为它的Source。然后,您将Image的Source(它是一个ImageSource对象)并将其字符串化。如果ImageSource来自文件或URL,这可能会有效,但它不会:它来自HBITMAP。所以ToString()的结果是没有意义的。所以ImageSource被设置为无意义的东西,而你的Image正试图将这种无意义的东西解释为位图文件的URL。

因此,要解决这个问题,你需要做三件事情:

  1. 提高了ImageSource的财产PropertyChanged事件(或使其依赖属性)。
  2. 将ImageSource属性更改为ImageSource类型而不是字符串类型(以便它可以包含无URL的图像源)。
  3. 更改您的setter调用以将ImageSource设置为Base64StringToImage(...).Source - 即移除ToString()调用。更好的是,将Base64StringToImage更改为返回ImageSource而不是Image:创建Image元素只会创建开销,因为您真正感兴趣的是BitmapSource。
+0

'Image.Source'也可以绑定到'Stream'或'byte []' – Schneider 2017-02-15 06:04:29