Retrieving image from binary data (OLE Object, Access database) and display it in DataGrid column in WPF (by C#)

رضا جافری 1,291 Reputation points
2021-07-14T18:36:16.79+00:00

First and foremost, I apologize for my grammatical errors; my first language is Persian (Iran).
I want to display the images in the DataGrid column where the binary are stored in Access.
The following method converts the image to binary:

 private static byte[] ImageToBytes(BitmapImage image)  
 {  
     byte[] Data;  
     JpegBitmapEncoder JpegEncoder = new JpegBitmapEncoder();  
     JpegEncoder.Frames.Add(BitmapFrame.Create(image));  
     using (System.IO.MemoryStream MS = new System.IO.MemoryStream())  
     {  
         JpegEncoder.Save(MS);  
         Data = MS.ToArray();  
     }  
     return Data;  
 }  

I receive the Bitmap image from the method below and then display it in the Image control:

 private BitmapImage GetImageFromBytes(byte[] bytes)  
 {  
     System.IO.MemoryStream Stream = new System.IO.MemoryStream();  
     Stream.Write(bytes, 0, bytes.Length);  
     Stream.Position = 0;  
     System.Drawing.Image img = System.Drawing.Image.FromStream(Stream);  
     BitmapImage bitImage = new BitmapImage();  
     bitImage.BeginInit();  
     System.IO.MemoryStream MS = new System.IO.MemoryStream();  
     img.Save(MS, System.Drawing.Imaging.ImageFormat.Jpeg);  
     MS.Seek(0, System.IO.SeekOrigin.Begin);  
     bitImage.StreamSource = MS;  
     bitImage.EndInit();  
     return bitImage;  
 }  

114731-first-image.jpg

public OleDbConnection OleDbConnect = new   
OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +   
System.Windows.Forms.Application.StartupPath + @"\Database.accdb");  
private void Window_Loaded(object sender, RoutedEventArgs e)  
{  
    OleDbConnect.Open();  
    OleDbDataAdapter OleDA = new OleDbDataAdapter("Select * From   
    MemberTable", OleDbConnect);  
    DataTable DT = new DataTable();  
    OleDA.Fill(DT);  
    for (int i = 0; i < DT.Rows.Count; i++)  
    {  
     //I want to convert all the cells in this column (members images -  
     //column)  
     //from the byte array to the bitmap image  
     var Temp = DT.Rows[i][12];  
     byte[] T = (byte[])Temp;  
     DT.Rows[i][12] = GetImageFromBytes(T);  
    }  
    MemberDataGrid.DataContext = DT;  
}  

But the above method for displaying the image in the DataGrid does not work properly:

114732-second-image.jpg

Thanks

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,524 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
778 questions
{count} votes

Accepted answer
  1. رضا جافری 1,291 Reputation points
    2021-07-25T21:16:02.17+00:00

    I found the solution.
    First, add the database to your project as shown below:

    117722-adding-database.gif

    Note: set the "Copy to Output Direct" property to "Copy if newer".

    Next, add the following XAML code to the window where you want the DataGrid to be displayed (You can add or remove columns as you wish):

    <Window.Resources>  
       <local:DatabaseDataSet x:Key="Database_DataSet"/>  
       <CollectionViewSource x:Key="MemberTableViewSource" Source="{Binding MemberTable, Source= {StaticResource Database_DataSet}}"/>  
    </Window.Resources>  
    <Grid DataContext="{StaticResource MemberTableViewSource}">  
      <DataGrid x:Name="MemberDataGrid" HeadersVisibility="Column" EnableRowVirtualization="True" AutoGenerateColumns="False" ItemsSource="{Binding}" Width="500" Height="400">  
        <DataGrid.Columns>  
          <DataGridTextColumn x:Name="FirstName" Binding="{Binding FirstName}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="LastName" Binding="{Binding LastName}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="IDNumber" Binding="{Binding IDNumber}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="PhoneNumber" Binding="{Binding PhoneNumber}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="MobilePhoneFirstNumber" Binding="{Binding MobilePhoneFirstNumber}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="MobilePhoneSecondNumber" Binding="{Binding MobilePhoneSecondNumber}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="LoanDate" Binding="{Binding LoanDate}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="NumberOfBooksTaken" Binding="{Binding NumberOfBooksTaken}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="BookReturnDate" Binding="{Binding BookReturnDate}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="MembershipDate" Binding="{Binding MembershipDate}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="RegistrationFee" Binding="{Binding RegistrationFee}" Width="SizeToHeader"/>  
          <DataGridTextColumn x:Name="QR" Binding="{Binding QR}" Width="auto"/>  
          <DataGridTemplateColumn x:Name="MemberImage" Width="SizeToHeader">  
            <DataGridTemplateColumn.CellTemplate>  
              <DataTemplate>  
                <Image Source="{Binding MemberImage}"/>  
              </DataTemplate>  
            </DataGridTemplateColumn.CellTemplate>  
          </DataGridTemplateColumn>  
        </DataGrid.Columns>  
      </DataGrid>  
    </Grid>  
    

    Then, add the following code to the window where you want the database information to be displayed in the DataGrid:

    public void DatagridRefresh()  
    {  
     DatabaseDataSet Database_DataSet = ((DatabaseDataSet)TryFindResource("Database_DataSet"));  
     DatabaseDataSetTableAdapters.MemberTableTableAdapter MemberTable_TableAdapter = new   
     DatabaseDataSetTableAdapters.MemberTableTableAdapter();  
     MemberTable_TableAdapter.Fill(Database_DataSet.MemberTable);  
     CollectionViewSource MemberTableViewSource =   
     ((CollectionViewSource)TryFindResource("MemberTableViewSource"));  
     MemberTableViewSource.View.MoveCurrentToFirst();  
    }  
    public MainWindow()  
    {  
    InitializeComponent();  
    DatagridRefresh();  
    }  
    

    Note: DatagridRefresh method must be used to update DataGrid (after inserting, editing and deleting).

    For example:

    private void Delete_Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)  
    {  
     OleDbConnection OleDbConnect = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source="   
     + System.Windows.Forms.Application.StartupPath + @"\Database.accdb");  
     OleDbConnect.Open();  
     OleDbCommand OleDbCommand_Delete = new OleDbCommand("Delete From [MemberTable] Where   
     [IDNumber]=" + IDNumber_TextBox.Text.Trim(), OleDbConnect);  
     OleDbCommand_Delete.ExecuteNonQuery();  
     OleDbConnect.Close();  
     var MainWindow = Application.Current.MainWindow;  
     (MainWindow as MainWindow).MemberDatagridRefresh();  
    }  
    

    Result:

    117731-result.gif

    Thanks

    0 comments No comments

0 additional answers

Sort by: Most helpful