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

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

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

ソースコード

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

デザイン (UserControl1.xaml)

        <Path Margin="4.1cm, 1.7cm, 0, 0" Width="1.5cm" Height="1.5cm" xName="QRCodeImage" Data="" Fill="Black" Stretch="Uniform" />
        
        <StackPanel Margin="0.6cm, 3.1cm, 0, 0">
            <Path Width="3cm" Height="0.4cm" xName="Code128Image" Data="" Fill="Black" Stretch="Uniform" />
            <TextBlock Height="0.25cm" xName="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} 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)

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} 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が使用出来て解像度の事を考えなくてよくなるので、幅が広がりそうです。

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