2010-04-04 34 views
8

Tôi có dưới mã XAML:Binding Image.Source vào chuỗi trong 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> 

Ngoài ra, có một phương pháp mà làm cho một hình ảnh từ một chuỗi 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; 
    } 
} 

Bây giờ, tôi sẽ ràng buộc TestImage đến đầu ra của Base64StringToImage phương pháp.
Tôi đã sử dụng cách sau:

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

nhưng không có gì xảy ra.
Làm cách nào để khắc phục sự cố?

BTW, tôi chắc chắn rằng chuỗi base64 là chính xác

+0

Không liên quan đến câu hỏi của bạn, nhưng bạn đã thử tải hình ảnh với 'var img = new BitmapImage {StreamSource = ms} '? –

+0

@Simon: KHÔNG, tôi chưa có. nhưng, Tại sao tôi lại làm vậy? –

+3

Vâng, bạn có thể tải hình ảnh trực tiếp với WPF, thay vì thông qua GDI + (System.Drawing). Bởi vì nó có nghĩa là để được sử dụng từ XAML, bạn thực sự phải làm 'var source = new BitmapImage(); source.BeginInit(); source.StreamSource = ms; source.EndInit() '. –

Trả lời

14

Là một bổ sung cho câu trả lời tuyệt vời @ itowlson, đây là những gì mã của bạn sẽ giống như thế:

// 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

Cảm ơn, tôi đã thực hiện nó, nhưng không có gì cho thấy. Chỉ một chuỗi được hiển thị thay vì image => 'WpfApplication1.MainModel'. bạn có thể tải xuống dự án của tôi từ http://www.mediafire.com/?nze3qjmzjtm –

+0

Gần như, đó là 'DataContext = model;', không phải 'Content = model;'. Ngoài ra, bạn có thể sử dụng 'Convert.FromBase64String (...)' trực tiếp trong 'SetImageData()', 'BitmapImage' có thể tải cùng một hình ảnh như' System.Drawing.Image'. –

+0

Cảm ơn bạn rất nhiều bro, tôi thực sự cần nó. Cảm ơn :-) –

22

Hãy chia nhỏ những gì bạn đang làm.

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

Để làm việc này, nguồn ràng buộc cần phải là ImageSource hoặc chuỗi đại diện cho URI thành tệp hình ảnh. Vì vậy, chúng ta hãy xem những gì các tài sản ImageSource thực sự là.

public string ImageSource { get; set; } 

Một vấn đề ở đây là ImageSource không tăng sự kiện PropertyChanged. Vì vậy, WPF sẽ không cập nhật các mục tiêu ràng buộc khi bạn cập nhật các tài sản.

Nhưng đồng thời, ImageSource không phải là ImageSource, nó là một chuỗi. Không sao, nhưng WPF sẽ giải thích chuỗi đó là một URI. URI đó là gì?

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

Đây là vấn đề của bạn. Chuỗi ImageSource không thực sự là một URI, bởi vì hình ảnh của bạn không phải là một tài nguyên địa chỉ. Base64StringToImage tạo một ImageSource trong bộ nhớ từ chuỗi base64, sau đó trả về một Ảnh với nguồn của nó. Sau đó, bạn lấy Source của Image (là một đối tượng ImageSource), và stringise đó. Điều đó có thể hoạt động nếu ImageSource đã đến từ một tệp hoặc URL, nhưng nó không: nó đến từ một HBITMAP. Vì vậy, kết quả của ToString() sẽ là vô nghĩa. Vì vậy, ImageSource đang được thiết lập để một cái gì đó vô nghĩa, và hình ảnh của bạn đang cố gắng để giải thích điều này vô nghĩa như URL của một tập tin bitmap.

Vì vậy, để khắc phục điều này bạn cần phải làm ba việc:

  1. Nâng cao sự kiện PropertyChanged cho các tài sản ImageSource (hoặc làm cho nó một tài sản phụ thuộc).
  2. Thay đổi thuộc tính ImageSource thành loại ImageSource thay vì loại chuỗi (để nó có thể chứa các nguồn hình ảnh không có URL).
  3. Thay đổi cuộc gọi setter của bạn để đặt ImageSource thành Base64StringToImage(...).Source - tức là xóa cuộc gọi ToString(). Vẫn còn tốt hơn, thay đổi Base64StringToImage để trả về một ImageSource chứ không phải là một hình ảnh: tạo ra một phần tử hình ảnh chỉ tạo ra overhead vì tất cả những gì bạn thực sự quan tâm là BitmapSource.
+0

'Image.Source' cũng có thể bị ràng buộc vào một' Stream' hoặc 'byte []' – Schneider