Привязка изображения. Источник для строкового представления в WPF?

Я имею ниже кода XAML:

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

Кроме того, существует метод, который делает Изображение из a 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;
    }
} 

Теперь, я собираюсь связывать TestImage к выводу Base64StringToImage метод.
Я использовал следующий путь:

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

но ничего не происходит.
Как я могу зафиксировать его?

BTW, я абсолютно уверен, что строка base64 корректна

8
задан Mohammad Dayyan 4 April 2010 в 08:27
поделиться

2 ответа

Вот как должен выглядеть ваш код в дополнение к отличному ответу @ 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));
        }
    }
}
16
ответ дан 5 December 2019 в 04:55
поделиться

Давайте разберемся, что вы делаете.

<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 создает в памяти ImageSource из строки base64, а затем возвращает изображение с этим в качестве источника. Затем вы берете Image's Source (который является объектом ImageSource) и структурируете его. Это могло бы сработать, если бы ImageSource был получен из файла или URL-адреса, но это не так: он поступил из HBITMAP. Таким образом, результат ToString () будет бессмысленным. Итак, ImageSource устанавливается на что-то бессмысленное, и ваше изображение пытается интерпретировать эту бессмысленную вещь как URL-адрес файла растрового изображения.

Итак, чтобы исправить это, вам нужно сделать три вещи:

  1. Вызвать событие PropertyChanged для свойства ImageSource (или сделать его свойством зависимости).
  2. Измените свойство ImageSource на тип ImageSource вместо строки типа (чтобы оно могло содержать источники изображений без URL).
  3. Измените вызов установщика, чтобы установить ImageSource на Base64StringToImage (...). Source - т.е. удалите вызов ToString (). Еще лучше измените Base64StringToImage, чтобы он возвращал ImageSource, а не Image: создание элемента Image просто создает накладные расходы, потому что все, что вас действительно интересует, - это BitmapSource.
22
ответ дан 5 December 2019 в 04:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: