製造業 スマートDX推進課 スマート工場DIY日記

製造業で働いているごく普通の社内SEです。日々の活動で生まれた成果物を共有します。

【C# .NET8.0】XAMLにQRコードをSVGで表示【ZXing.NET】

XAMLを使用して帳票を作成する際に、QRコードを表示したいが
ZXingだとImageの変換が必要となるらしいので、この際ZXingで新しく実装された
SVG出力の機能でQRコードを表示してみました。解像度的にもSVGの方が良い為。

1次元バーコードの表示も併用可能です。

ソースコード

NuGetパッケージマネージャー より ZXing.NET (Ver.0.16.6以上)をインストールしてください。
今回は Ver.0.16.9 を使用しています。

デザイン (UserControl1.xaml)

            <!--QRCode-->
            <Path Margin="4.1cm, 1.7cm, 0, 0" Width="1.5cm" Height="1.5cm" x:Name="QRCodeImage" Data="" Fill="Black" Stretch="Uniform" />
            <!--Code128-->
            <StackPanel Margin="0.6cm, 3.1cm, 0, 0">
                <Path Width="3cm" Height="0.4cm" x:Name="Code128Image" Data="" Fill="Black" Stretch="Uniform" />
                <TextBlock Height="0.25cm" x:Name="Code128Text" FontSize="0.15cm" TextAlignment="Center" Text="" />
            </StackPanel>

 

データバインディング (UserControl1.xaml.cs)

        private string? _QRCode;
        private string? _Code128;

        public string QRCode
        {
            get => this._QRCode ?? "";
            set
            {
                this._QRCode = value;
                CreateBarcode(QRCodeImage, this._QRCode, BarcodeFormat.QR_CODE);
            }
        }
        public string Code128
        {
            get => this._Code128 ?? "";
            set {
                this._Code128 = value;
                CreateBarcode(Code128Image, this._Code128, BarcodeFormat.CODE_128);
            }
        }

        private void CreateBarcode(Path path, string text, BarcodeFormat barcodeFormat)
        {
            string data = "F1 ";
            foreach (
                XElement el in XElement.Parse(
                    new BarcodeWriter<SvgRenderer.SvgImage>
                    {
                        Format = barcodeFormat,
                        Options = new QrCodeEncodingOptions
                        {
                            ErrorCorrection = ErrorCorrectionLevel.M,
                            CharacterSet = "UTF-8",
                            NoPadding = true,
                        },
                        Renderer = new SvgRenderer(),
                    }.Write(text).Content
                ).Elements())
            {
                if (el.Name.LocalName == "rect") {
                    string x = el.Attribute("x").Value;
                    string y = el.Attribute("y").Value;
                    string width = el.Attribute("width").Value;
                    string height = el.Attribute("height").Value;
                    //data += $"M{x},{y} v{height} h{width} v-{height} Z";
                    data += $"M{x},{y} h{width} v{height} h-{width} Z";
                    path.Data = (Geometry?)new GeometryConverter().ConvertFromInvariantString(data);
                }
                else if (el.Name.LocalName == "text")
                {
                    if (path == Code128Image) Code128Text.Text = el.Value;
                }
            }
        }

解説

デザイン (UserControl1.xaml)

<Path Margin="4.1cm, 1.7cm, 0, 0" Width="1.5cm" Height="1.5cm" x:Name="QRCodeImage" Data="" Fill="Black" Stretch="Uniform" />

Margin は表示位置を指定しています。
WidthHeightQRコードのサイズです。親要素のサイズに合わせたい場合は削除してください。
x:Name はデータバインディングで使用する名前です。

CODE128は StackPanel でまとめて Path の下に TextBlock を追加しています。文字列を Path に変換出来ない為です。

 

データバインディング (UserControl1.xaml.cs)

        private string? _QRCode;
        public string QRCode
        {
            get => this._QRCode ?? "";
            set
            {
                this._QRCode = value;
                CreateBarcode(QRCodeImage, this._QRCode, BarcodeFormat.QR_CODE);
            }
        }

プロパティを使用し set でバーコード作成メソッドを呼び出し、Path に反映させています。

 

        private void CreateBarcode(Path path, string text, BarcodeFormat barcodeFormat)
        {
            string data = "F1 ";
            foreach (
                XElement el in XElement.Parse(
                    new BarcodeWriter<SvgRenderer.SvgImage>
                    {
                        Format = barcodeFormat,
                        Options = new QrCodeEncodingOptions
                        {
                            ErrorCorrection = ErrorCorrectionLevel.M,
                            CharacterSet = "UTF-8",
                            NoPadding = true,
                        },
                        Renderer = new SvgRenderer(),
                    }.Write(text).Content
                ).Elements())
            {
                if (el.Name.LocalName == "rect") {
                    string x = el.Attribute("x").Value;
                    string y = el.Attribute("y").Value;
                    string width = el.Attribute("width").Value;
                    string height = el.Attribute("height").Value;
                    //data += $"M{x},{y} v{height} h{width} v-{height} Z";
                    data += $"M{x},{y} h{width} v{height} h-{width} Z";
                    path.Data = (Geometry?)new GeometryConverter().ConvertFromInvariantString(data);
                }
                else if (el.Name.LocalName == "text")
                {
                    if (path == Code128Image) Code128Text.Text = el.Value;
                }
            }
        }

バーコード作成メソッドです。

変数 dataPath 表示に使用する文字列を入れていきます。
先頭の F1 は塗潰しオプションなので必須です。

ZXing からの戻り値が XML で返ってくるため、SVGタグ のみを取り出します。

new BarcodeWriter<SvgRenderer.SvgImage> で 戻り値を SVG に指定しています。

あとは、SVG⇒Path変換の処理なので説明は省略します。詳しく知りたい場合は、Pathの使用を見てください。

developer.mozilla.org

あとがき

ZXing最新バージョンを使用した際に、今までのソースコードが使えなくて戸惑ってましたが
まさか出力フォーマットが指定できるようになっていたとは、目から鱗です。

SVGが使用出来て解像度の事を考えなくてよくなるので、幅が広がりそうです。

今後、バーコードを使用した帳票の作成方法も記事にしたいと思います。