Click here to Skip to main content
14,638,900 members

Help needed debugging conversion of a byte array to an image in WPF datagrid.

Ger Hayden asked:

Open original thread
The following code complies and runs but the byte array (p_photo) is never shown either on the datagrid or the details template. When I put it into debug the breakpoint in the converter is not hit so I suspect the problem is around that. I cannot spot it so any assistance would be appreciated.

What I have tried:

This is my XAML:
<Window x:Class="SharedUIForms.Person"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SharedUIForms"
        mc:Ignorable="d"
        Title="PersonMaster" Height="450" Width="800"
        WindowStartupLocation="CenterScreen" WindowState="Maximized">
    <Window.Resources>
        <local:ByteArrayToImageSourceConverter x:Key="ByteArrayToImageSourceConverter" />
    </Window.Resources>
    <Grid ShowGridLines ="True" Background ="LightSteelBlue">
        <Grid.Resources>
            <DataTemplate x:Key="DataTemplate">
                <Image Name ="PersonImage" Height="100" Source="{Binding p_photo, Converter={StaticResource ByteArrayToImageSourceConverter}}" />
            </DataTemplate>
        </Grid.Resources>
        <!-- Define the rows/columns -->
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="9*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <!-- Now add the elements to the grid's cells -->
        <!-- Data grid for the datastore details -->
        <DataGrid ItemsSource="{Binding Persons}"  AlternatingRowBackground="Gainsboro"  AlternationCount="2"  Grid.Row ="0" AutoGenerateColumns="false">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Binding="{Binding p_PersonID}" />
                <DataGridTextColumn Header="Forename" Binding="{Binding p_Forename}" />
                <DataGridTextColumn Header="Surname" Binding="{Binding p_Surname}" />
                <DataGridTextColumn Header="Address 1" Binding="{Binding p_Address1 }" />
                <DataGridTextColumn Header="Address 2" Binding="{Binding p_Address2 }" />
                <DataGridTextColumn Header="Address 3" Binding="{Binding p_Address3 }" />
                <DataGridTextColumn Header="Address 4" Binding="{Binding p_Address4 }" />
                <DataGridTextColumn Header="Email" Binding="{Binding p_Email_Addr}" />
                <DataGridTextColumn Header="Mobile Tel" Binding="{Binding p_Mobile_Tel}" />
                <DataGridTextColumn Header="Registered" Binding="{Binding p_Registered}" />
                <DataGridTextColumn Header="Date Entered" Binding="{Binding p_DateEntered}" />
                <!--<DataGridTemplateColumn Header="Picture" CellTemplate="{StaticResource DataTemplate}"/>-->
            </DataGrid.Columns>
            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <Grid ShowGridLines ="True" Background ="LightSteelBlue">
                        <!-- Define the rows/columns -->
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <StackPanel Grid.Column="0">
                            <Image Name ="PersonImage" Height="100" Source="{Binding p_photo, Converter={StaticResource ByteArrayToImageSourceConverter}}" />
                            <Button x:Name="btnImage" Width ="80" Content="Add Image" Click="btnImage_Click"/>
                        </StackPanel>
                        <StackPanel Grid.Column="1" Background="LightSteelBlue">
                            <TextBlock Text="ID: " FontWeight="Bold" />
                            <TextBlock Text="{Binding p_PersonID}" />
                            <TextBlock Text="Surname: " FontWeight="Bold" />
                            <TextBlock Text="{Binding p_Surname}" Grid.Column="1" />
                            <TextBlock Text="Forename: " FontWeight="Bold" />
                            <TextBlock Text="{Binding p_Forename}" Grid.Column="1" />
                            <TextBlock Text="Email: " FontWeight="Bold" />
                            <TextBlock Text="{Binding p_Email_Addr}" Grid.Column="1" />
                            <TextBlock Text="Moblile Telepone: " FontWeight="Bold" />
                            <TextBlock Text="{Binding p_Mobile_Tel}" Grid.Column="1" />
                            <TextBlock Text=" " FontWeight="Bold" />
                        </StackPanel>
                        <StackPanel Grid.Column="2"></StackPanel>
                        <StackPanel Grid.Column="3"></StackPanel>
                    </Grid>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>

        </DataGrid>

        <!-- Button grid for the controls -->
        <Grid ShowGridLines ="True" Background ="LightCyan" Grid.Row ="1">
            <!-- Define the rows/columns -->
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Button x:Name="btnCommit" Height ="30"  Width="100" Grid.Column ="0"
                    Grid.Row ="0" Content="Commit" Click="btnCommit_Click"/>
            <Button x:Name="btnRollback" Height ="30" Width="100" Grid.Column ="1"
                    Grid.Row ="0" Content="Rollback" Click="btnRollback_Click"/>
            <Button x:Name="btnExit" Height ="30" Width="100" Grid.Column ="2"
                    Grid.Row ="0" Content="Exit" Click="btnExit_Click"/>
        </Grid>
    </Grid>
</Window>


This is the code behind it:
using log4net;
using Microsoft.Win32;
using SharedModels.Models.Pages;
using SharedUIForms.Models.ViewModels;
using System;
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using VTInfrastructure.Other;

namespace SharedUIForms
{
    public class ByteArrayToImageSourceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            byte[] imageData = (byte[])value;

            BitmapImage biImg = new BitmapImage();
            MemoryStream ms = new MemoryStream(imageData);
            biImg.BeginInit();
            biImg.StreamSource = ms;
            biImg.EndInit();

            ImageSource imgSrc = biImg as ImageSource;

            return imgSrc;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Stream stream = (Stream)value;
            Byte[] buffer = null;
            if (stream != null && stream.Length > 0)
            {
                using (BinaryReader br = new BinaryReader(stream))
                {
                    buffer = br.ReadBytes((Int32)stream.Length);
                }
            }

            return buffer;
        }
    }

    /// <summary>
    /// Interaction logic for Person.xaml
    /// </summary>
    public partial class Person : Window
    {
 
        public Person(string accessToken, ILog logger)
        {
            InitializeComponent();

            this.options = new QueryOptions();
            AppSettingsReader ar = new AppSettingsReader();
            this.ldh = new LocalDataHandler(logger, ar);
            DataContext = new PersonViewModel(accessToken, this.ldh, this.options, logger);
        }

        private void btnCommit_Click(object sender, RoutedEventArgs e)
        {

        }

        private void btnRollback_Click(object sender, RoutedEventArgs e)
        {

        }

        private void btnImage_Click(object sender, RoutedEventArgs e)
        {
            BitmapImage bitmapImage;
            byte[] imageAsByteArray;

            var of = new OpenFileDialog();
            of.Filter = "Image files (*.bmp;*.png;*.jpg;*.jpeg)|*.bmp;*.png;*.jpg;*.jpeg|All files (*.*)|*.*";
            var res = of.ShowDialog();
            if (res.HasValue)
            {
                using (FileStream stream = new FileStream(of.FileName, FileMode.Open, FileAccess.Read))
                {
                    using (var reader = new BinaryReader(stream))
                    {
                        imageAsByteArray = reader.ReadBytes((int)stream.Length);

                    }
                    using (MemoryStream byteStream = new MemoryStream(imageAsByteArray))
                    {
                        BitmapImage image = new BitmapImage();
                        image.BeginInit();
                        image.StreamSource = byteStream;
                        //    image.CacheOption = BitmapCacheOption.OnLoad;
                        image.EndInit();
                        //    image.Freeze();
                        e.Source = image;
                    }
                }
            }
        }
 
        private void btnExit_Click(object sender, RoutedEventArgs e)
        {
            // Close this window.
            this.Close();
        }

        #region PRIVATE VARIABLES

        private LocalDataHandler ldh;
        QueryOptions options;

        #endregion

    }

 
}


And the viewModel:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using VTInfrastructure.Other;
using log4net;
using SharedModels.Models;
using SharedModels.Models.Pages;
using System.Threading.Tasks;
using System.Windows.Data;
using Newtonsoft.Json;

namespace SharedUIForms.Models.ViewModels
{
    public class PersonViewModel
    {
        private LocalDataHandler ldh;
        private ILog logger;
        private string accessToken;
        private QueryOptions options;

        public ICollectionView Persons { get; private set; }
        private IList<CPersonMasterBase> personDataset;

        public PersonViewModel(string AccessToken, LocalDataHandler Ldh, QueryOptions Options,  ILog Logger)
        {
            this.ldh = Ldh;
            this.logger = Logger;
            this.accessToken = AccessToken;
            this.options = Options;
            
            GetPersonDataSet();
            this.Persons = CollectionViewSource.GetDefaultView(this.personDataset);

        }

        private async Task GetPersonDataSet()
        {
            this.personDataset = new List<CPersonMasterBase>();
         
            var task = this.ldh.GetAllPersons(accessToken, this.options);
            task.Wait(); // Blocks current thread until GetAllPersons task completes
                         // For pedagogical use only: in general, don't do this!
            this.personDataset = task.Result;

         //            this.personDataset = await this.ldh.GetAllPersons(accessToken, this.options);
        }
    }
}
Tags: C#

Preview



When answering a question please:
  1. Read the question carefully.
  2. Understand that English isn't everyone's first language so be lenient of bad spelling and grammar.
  3. If a question is poorly phrased then either ask for clarification, ignore it, or edit the question and fix the problem. Insults are not welcome.
  4. Don't tell someone to read the manual. Chances are they have and don't get it. Provide an answer or move on to the next question.
Let's work to help developers, not make them feel stupid.
Please note that all posts will be submitted under the The Code Project Open License (CPOL).




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100