Binding Image.Source to String in WPF?
我有以下XAML代码:
1 2 3 4 5 6 7 8 9 10 11 12 | <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> |
此外,还有一种方法可以从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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; } } |
现在,我将
我使用以下方式:
1 2 | 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字符串是正确的
让我们分解一下你在做什么。
1 | <Image Source="{Binding ImageSource}" /> |
为此,绑定源必须是ImageSource或表示图像文件URI的字符串。因此,让我们看一下ImageSource属性实际上是什么。
1 | public string ImageSource { get; set; } |
这里的一个问题是ImageSource没有引发PropertyChanged事件。因此,当您更新属性时,WPF不会更新绑定目标。
但是,ImageSource不是ImageSource,它是一个字符串。没关系,但是WPF会将字符串解释为URI。该URI是什么?
1 | ImageSource = Base64StringToImage(BIG_HONKING_STRING).Source.ToString(); |
这是您的问题所在。 ImageSource字符串实际上不是URI,因为您的图像不是可寻址资源。 Base64StringToImage从base64字符串创建一个内存ImageSource,然后返回一个以ImageImage作为其Source的Image。然后,获取图像的Source(它是一个ImageSource对象),并将其字符串化。如果ImageSource来自文件或URL,则可能会起作用,但并非如此:它来自HBITMAP。因此,ToString()的结果将毫无意义。因此,将ImageSource设置为无意义的东西,并且您的Image试图将无意义的东西解释为位图文件的URL。
因此,要解决此问题,您需要做三件事:
作为@itowlson出色答案的补充,这是您的代码应如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | // 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)); } } } |