You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF扫码后自动重置/刷新TextBox的实现方法

实现WPF扫码枪连续扫码无需手动清空TextBox的方案

问题背景

我正在开发一款简易WPF程序,用户使用USB扫码枪扫描条码后,程序会将数据直接发送至云ERP。目前程序可正常运行,但用户扫码后需手动点击TextBox并清除数据才能再次扫码,希望实现打开软件后可连续扫码,无需手动清空TextBox。

现有代码

MainWindow.xaml

<Window x:Class="ProductionScanner.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:viewModel="clr-namespace:ProductionScanner.MVVM.ViewModel"
    xmlns:local="clr-namespace:ProductionScanner"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800"
    Background="#181735" >

<Window.DataContext>
    <viewModel:ReceiptViewModel />
</Window.DataContext>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="25" />
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <Grid Background="#0F0F2D"
          Grid.ColumnSpan="2">

        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
         
        </Grid.ColumnDefinitions>

        <TextBlock Text="Foods"
                   Foreground="White"
                   Grid.Column="1"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Left"
                   />
        <TextBlock Text="Records"
                   Foreground="White"
                   Grid.Column="2"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center"
                   />
    </Grid>

    <StackPanel FocusManager.FocusedElement="{Binding ElementName=txtIniFocus}">

        <TextBox x:Name="txtIniFocus" Margin="6" Text="{Binding Barcode, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Top" Width="150" Grid.Row="1" TextChanged="TextBox_TextChanged">
            <TextBox.InputBindings>
                <KeyBinding Key="Enter" Command="{Binding ReceiptCommand}" />
            </TextBox.InputBindings>
        </TextBox>

    </StackPanel>

</Grid>

ReceiptViewModel.cs

using ProductionScanner.Cores;
using ProductionScanner.MVVM.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Windows;
using System.Windows.Controls.Primitives;

namespace ProductionScanner.MVVM.ViewModel
{
    public class ReceiptViewModel: ObservableObject
    {
        private string _barcode;

        public string Barcode
        {
            get { return _barcode; }
            set { _barcode = value; OnPropertyChanged(); }
        }

        public RelayCommand ReceiptCommand { get; set; }
        public ReceiptViewModel()
        {
            ReceiptCommand = new RelayCommand(x =>
            {
                receiptInventory();
            });
        }

    private void receiptInventory()
    {
        if (Barcode.Length == 12)
        {
            var inventoryIDFrom = Barcode.Substring(0, 6);
            var kgIntFrom = Barcode.Substring(6);
            var kgDecimalFrom = kgIntFrom.Substring(0,kgIntFrom.Length-4) + "." + kgIntFrom.Substring(kgIntFrom.Length - 4, 3);
            ERPRestService _erpRestService = new ERPRestService();
            ReceiptItems receiptItems = new ReceiptItems();
            receiptItems.InventoryID = inventoryIDFrom;
            receiptItems.Qty = Convert.ToDecimal(kgDecimalFrom);
            receiptItems.WarehouseID = "WH001";
            receiptItems.LocationID = "L001";
            receiptItems.LotSerialNbr = "";
            receiptItems.ExpirationDate = DateTime.Now;
            try
            {
                var jsonObj1 = new
                {
                    Description = new
                    {
                        value = "Receipt"
                    },
                    Hold = new
                    {
                        value = false
                    },
                    Details = new[]
                    {
                    new {
                        InventoryID = new
                        {
                            value = receiptItems.InventoryID
                        },
                        Qty = new
                        {
                            value = receiptItems.Qty
                        },
                        WarehouseID = new
                        {
                            value = receiptItems.WarehouseID
                        },
                        Location = new
                        {
                            value = receiptItems.LocationID
                        }
                    }
                }

                };
                string entityAsString = JsonConvert.SerializeObject(jsonObj1);
                //string parameters1 = "$expand=Details";
                var receipt = _erpRestService.Put("InventoryReceipt", null, entityAsString);
                string refRelease = JObject.Parse(receipt)["ReferenceNbr"]["value"].ToString();
                var release = new
                {
                    entity = new
                    {
                        ReferenceNbr = new
                        {
                            value = refRelease
                        }
                    }
                };
                string jsonRelease = JsonConvert.SerializeObject(release);
                jsonRelease = _erpRestService.Post("InventoryReceipt", "ReleaseInventoryReceipt", jsonRelease);
                MessageBox.Show("Your AR Confirm has completed.", "Confirm", MessageBoxButton.OK, MessageBoxImage.Information);
            }

            
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                _erpRestService.Dispose();
            }
        }
    }
}

解决方案

要实现连续扫码,核心是完成扫码处理后自动清空绑定的条码字段,并确保TextBox始终保持焦点。

方法1:命令执行完成后自动清空条码

修改receiptInventory方法的finally块,添加清空Barcode字段的代码,绑定的TextBox会自动同步清空,且初始设置的焦点会保留,下次扫码可直接输入:

finally
{
    _erpRestService.Dispose();
    // 清空条码绑定字段,TextBox会自动同步清空
    Barcode = string.Empty;
}

这种方式适配绝大多数扫码枪(扫码枪通常会自动追加回车触发ReceiptCommand),逻辑简洁且不易出错。

方法2:通过TextChanged事件自动触发处理(适配无回车的扫码场景)

如果扫码枪不会自动追加回车,可通过TextBox的TextChanged事件,在条码长度符合要求时自动触发命令并清空:
在MainWindow.xaml.cs中添加事件处理代码:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    var textBox = sender as TextBox;
    if (textBox == null) return;

    // 当条码长度达到设定的12位时,自动触发处理
    if (textBox.Text.Length == 12)
    {
        var viewModel = DataContext as ReceiptViewModel;
        viewModel?.ReceiptCommand.Execute(null);
        // 延迟清空确保命令处理完成
        Dispatcher.InvokeAsync(() => textBox.Text = string.Empty);
    }
}

额外注意事项

  • 若存在其他控件抢占焦点的情况,可在清空条码后主动调用txtIniFocus.Focus()确保焦点回到TextBox。
  • 避免重复触发:使用方法1时,回车触发命令后再清空条码,不会因TextChanged事件重复执行处理逻辑。

内容的提问来源于stack exchange,提问作者David Lightman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 22:50:23