In one of my previous posts https://sudiptach.wordpress.com/2017/07/01/generate-qr-code/, I had demonstrated how to generate QR code is an Angular4 application

In this application, I will demonstrate how to generate QR codes in vCard 3.0 format (https://en.wikipedia.org/wiki/VCard) which can be saved in your cell phone’s address book by scanning the QR Code

Source Code : Complete source code for the article at GitHub repo (along with sample excel sheet) https://github.com/sudipta-chaudhari/QRCode_WPF_vCard3.0

Use Case : A fictitious company’s HR department has an excel sheet with the employee data. HR department needs to upload this excel sheet in a desktop application. A button should be available for each employee data row which can be clicked to save the employee’s v3 format QR code.

Key Learnings :

(1) Create WPF DataGrid with paging & searching & ComboBox to change number of records displayed per page

(2) Generate v3 format QR Code

Technologies Used :

(1) WPF

(2) Open XML – for reading excel file and aggregating data in DataTable object

Third Party Libraries Used : ZXing.Net (v0.15.0) – can be installed from NuGet

Solution Design : Click the upload excel button. This will trigger an OpenFileDialog where you can browse and select the employee excel sheet.The excel sheet structure with sample data looks as below.

businesscard_qr_employee_excelsheet

The application’s home screen after uploading the employee excel sheet with sample data looks as below:

businesscard_qr_app_homescreen

For a employee row, click the “QR Code” button to generate and save the QR Code. For demonstration, I clicked the fifth row with first name “Sudipta4” and last name “Chaudhari4”. This will open a SaveFileDialog to save the QRCode image in format i.e. Sudipta4Chaudhari4.png. The saved QR Code image looks as below.

Sudipta4Chaudhari4.png

On scanning the QR Code using my cell phone with a bar code scanner app looks as shown below:

BusinessCardQR_Scan_Phone

Pressing Add contact opens phone’s contact manager app which populates the QR Code encode data in the contact fields as shown below:

BusinessCardQR_AddContact

Finally, after saving the contact, it look as below:

BusinessCardQR_ContactDetails

Code :

Step 1 : Create a WPF application. In the MainWindow.xaml, add the below code to layout the screen field elements using Grid and Stack Panel

<Window x:Class="BusinessCardQR.MainWindow"         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:BusinessCardQR"         mc:Ignorable="d"         Title="Business Card QRCode" Height="Auto" Width="1269.768" WindowStartupLocation="CenterScreen"          WindowStyle="ThreeDBorderWindow" WindowState="Maximized" ResizeMode="CanResizeWithGrip" StateChanged="Window_StateChanged"         Icon="qrcode_logo.ico">

    <Grid x:Name="FormLayout">

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100*" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height = "1.5*" />
            <RowDefinition Height = "8*" />
            <RowDefinition Height = "*" />
        </Grid.RowDefinitions>

        <Grid x:Name="glHeader">
            <Grid.Resources>
<Style TargetType="{x:Type Button}">
                    <Setter Property="Margin" Value="5,5,5,5"/>
                </Style>
<Style TargetType="{x:Type TextBlock}">
                    <Setter Property="TextWrapping" Value="Wrap"></Setter>
                    <Setter Property="TextAlignment" Value="Left"></Setter>
                </Style>

            </Grid.Resources>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.1*" />
                <ColumnDefinition Width="0.1*"/>
                <ColumnDefinition Width="0.3*" />
                <ColumnDefinition Width="0.25*"/>
                <ColumnDefinition Width="0.3*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Button Grid.Column="0" Content = "Upload Excel" HorizontalAlignment = "Left" VerticalAlignment = "Center"                  Width = "80" Height="30" Name="btnUploadExcel" Click="btnUploadExcel_Click" />
            <Button Grid.Column="1" Content = "Clear Sort" x:Name="btnClearSort" HorizontalAlignment = "Left" VerticalAlignment = "Center"                  Width = "80" Height="30" Click="btnClearSort_Click" />
            <TextBlock Grid.Column="2" Name="lblSearch" Text="Search" Padding="2" HorizontalAlignment = "Right" VerticalAlignment = "Center" />
            <TextBox x:Name="txtSearch" Grid.Column="3" Width="210" Height="20" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Left"                       TextChanged="txtSearch_TextChanged"/>
            <TextBlock x:Name="lblRecordToShow" Grid.Column="4" Margin="10" Text="Record to Show" HorizontalAlignment = "Right" VerticalAlignment = "Center" />
            <ComboBox x:Name="cmbRecordCount" Grid.Column="5" Width="60" Height="20" HorizontalAlignment = "Right" VerticalAlignment = "Center"                        SelectionChanged="cmbRecordCount_SelectionChanged" />
        </Grid>

        <DataGrid Name="dgEmployees" Grid.Row="1" Grid.Column="0" Margin="5 5 0 5" AutoGenerateColumns="False" HorizontalAlignment="Stretch"                   VerticalAlignment="Top" Width="Auto" ColumnWidth="100" RowHeight="30" Background="LightGray" RowBackground="LightYellow"                    AlternatingRowBackground="LightBlue" CanUserAddRows="False">

            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"></DataGridTextColumn>
                <DataGridTextColumn Header="Middle Name" Binding="{Binding MiddleName}"></DataGridTextColumn>
                <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"></DataGridTextColumn>
                <DataGridTextColumn Header="Organization" Binding="{Binding Organization}"></DataGridTextColumn>
                <DataGridTextColumn Header="Title" Binding="{Binding Title}"></DataGridTextColumn>
                <DataGridTextColumn Header="Mobile" Binding="{Binding Mobile}"></DataGridTextColumn>
                <DataGridTextColumn Header="Landline" Binding="{Binding Landline}"></DataGridTextColumn>
                <DataGridTextColumn Header="Fax" Binding="{Binding Fax}"></DataGridTextColumn>
                <DataGridTextColumn Header="Url" Binding="{Binding Url}"></DataGridTextColumn>
                <DataGridTextColumn Header="Email" Binding="{Binding Email}"></DataGridTextColumn>
                <DataGridTextColumn Header="Address" Binding="{Binding Address}" Width="220"></DataGridTextColumn>
                <DataGridTemplateColumn Width="*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Click="GenerateQRCode">QR Code</Button>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

        <StackPanel Grid.Row="2" Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center">
            <StackPanel.Resources>
<Style TargetType="{x:Type Button}">
                    <Setter Property="Margin" Value="5,5,5,5"/>
                </Style>

            </StackPanel.Resources>
            <Button x:Name="btnFirst" Content = "<<First" HorizontalAlignment = "Center" VerticalAlignment = "Center" Width = "80" Height="30" Click="btnFirst_Click" />
            <Button x:Name="btnPrevious" Content = "<Previous" HorizontalAlignment = "Center" VerticalAlignment = "Center" Width = "80" Height="30" Click="btnPrevious_Click" />
            <TextBlock x:Name="lblPager" Text="No Data Found" Margin="10" Width="250" HorizontalAlignment = "Center" VerticalAlignment = "Center" TextAlignment="Center" />
            <Button x:Name="btnNext" Content = "Next>" HorizontalAlignment = "Center" VerticalAlignment = "Center" Width = "80" Height="30" Click="btnNext_Click" />
            <Button x:Name="btnLast" Content = "Last>>" HorizontalAlignment = "Center" VerticalAlignment = "Center" Width = "80" Height="30" Click="btnLast_Click" />
        </StackPanel>

    </Grid>
</Window>

MainWindow.xaml.cs has all the code for:

  • OpenFileDialog – to upload excel sheet
  • Importing the excel sheet data using OpenXML to a DataTable object
  • Creating a WPF grid
  • Adding paging and searching functionality
  • Adding ComboBox to change the number of records displayed per page of the DataGrid
  • Adding template field to grid for button to generate QR code for every row of DataGrid
  • Generating the QR Code using ZXing.Net library
  • Saving the QR Code image using a SaveFileDialog by converting QR Code image to a Bitmap image and saving it to MemoryStream object for downloading
  • Clear Sort button clears the sorting if applied on the DataGrid by clicking the column headers to revert back to the original state where the data was uploaded from the excel sheet
  • UploadExcel button also checks if excel sheet is not in correct format (field names as set and shown in the excel sheet screenshot above in the article should be the same), warns the user using a MessageBox message display

You can download the complete source code for the article at GitHub repo (along with sample excel sheet)

https://github.com/sudipta-chaudhari/QRCode_WPF_vCard3.0

I hope you followed the article. If you have any comments, questions or suggestions, leave a message and I will try to respond at my earliest.