2010-04-04 227 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