xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.63k stars 1.88k forks source link

[Bug] Barcode Scanner triggers carriage return before reading all values #14996

Open NicolaZuc opened 2 years ago

NicolaZuc commented 2 years ago

Hi, i've discovered a strange behavior when using USB scanners in keyboard emulation mode with carriage returnon UWP. When i try to scan a value while i have focus on a control with a text input and a "completed" event, the completed event is triggered before that the scanner has read the other values.

To reproduce the problem: 1) put focus on an entry 2) scan a value from usb scanner in keyboard emulation mode

Expected Behavior

ReturnCommand triggered ReturnCommandParameter with value as entry.text = scanned barcode

Actual Behavior

ReturnCommand triggered ReturnCommandParameter with value as empty

Basic Information

However if i don't use ReturnCommandParameter and instead use a string binded in my view model and wait some time, the value then is correct. Example:

//xaml
<Entry Text={Binding EntryText}/>

//View model
private async void OnReturn(){ // in this situation the value is null
    if (string.IsNullOrEmpty(EntryText))
        Console.WriteLine("Error!")
}

private async void OnReturn(){ // in this situation the value is not null
    await Task.Delay(500);
    if (string.IsNullOrEmpty(EntryText))
        Console.WriteLine("Error!")
}

I've found similar problems here, here and here

jfversluis commented 2 years ago

Hey, thanks for the report! From what you're saying I think you might have a wrong understanding of ReturnCommandParameter. This property is something that serves as input. You can specify a value here that can be used inside of the command that you specify with ReturnCommand.

You should indeed get the value from the property that you are binding to in your view model. You might be confused with how events work. They indeed do have arguments that typically have informations about the event that just happened. That is not the case for commands.

Hope this helps!

NicolaZuc commented 2 years ago

You didn't understand my report. I know that returncommandparameter is used as an input, what i'm saying is that it is empty when i use it with a scanner! ReturnCommandParameter={Binding Source={x:Reference Entry}, Path=Text} If i write in my entry writing the text then the returncommandparameter has the correct value, else it is empty.

jfversluis commented 2 years ago

But still, how do you expect this to work? The text of that entry only gets filled when the return command is fired, so how is it supposed to act as an input at the same time? I'm probably not understanding what you are trying to do indeed, but to be honest it seems like me that you would want to solve this another way and this is not really a bug in our codebase.

NicolaZuc commented 2 years ago

if i write: "hello world" in my entry and then press enter, my returncommandparameter contains hello world. If i scan "hello world" with my scanner without carriage return then the entry contains hello world and then i press manually enter, my returncommandparameter contains hello world. If i scan "hello world" with my scanner with carriage return then the entry contains hello world and automatically press enter, my returncommandparameter contains empty. This doesn't seem a bug to you? Or did i not explain it correctly? If i can explain it better or u can explain me better where am i wrong in what i'm saying it would help me to understand, unfortunately my english is not so good so i'm trying to do my best. Thanks for your time

NicolaZuc commented 2 years ago

Can you please re-open the issue?

jfversluis commented 2 years ago

If you can provide me with a runnable reproduction of this problem in a GitHub repository that I can take a look at I think that might help clear things up.

NicolaZuc commented 2 years ago

i can give u a repro, but do u have an usb barcode scanner to test? Else u will never be able to detect the problem.

jfversluis commented 2 years ago

I do not, that is also part of the problem indeed :) But with a repro I might be able to poke around and see if I can detect where things might go wrong

NicolaZuc commented 2 years ago

Ok, i'll give you a repro the 10th of january, at the moment i'm on vacation and i don't have my equipment with me. Do you want also a video to show you the problem?

jfversluis commented 2 years ago

If you would be able to do that that would be awesome :)

NicolaZuc commented 2 years ago

Hi, i will give you a repro as soon as i can, atm there are some pandemic problems and i can't go to the office.

jfversluis commented 2 years ago

Sorry to hear that @NicolaZuc stay safe!

NicolaZuc commented 2 years ago

Hi and sorry for the delay. Here is an example of runnable code that will show you the problem and a video running with the barcode scanner. As you can see in the video, the value that is being read is empty in all cases except for the last one (binding value on text property of the entry and waiting 500ms). I've also used the barcode scanner in the notedpad to show how it works and which characters it use (read characters + return). If there is something else that i can give to you to let you better understand my problem just say it and i'll do my best.

Greetings, Nicola

repro.zip

NicolaZuc commented 2 years ago

Any news on this?

BoingDeFresa commented 2 years ago

Hi NicolaZuc can you resolve the issue? I got exactly the same problem as you. When i use the barcode scanner with the application i´m developing in Android or IOS there is no problem, but when i use it with UWP it sends an enter before it writes the content of the scanned code

NicolaZuc commented 2 years ago

Hi NicolaZuc can you resolve the issue? I got exactly the same problem as you. When i use the barcode scanner with the application i´m developing in Android or IOS there is no problem, but when i use it with UWP it sends an enter before it writes the content of the scanned code

Unfortunately no, i'm waiting that @jfversluis updates me on this matter

NicolaZuc commented 2 years ago

Can i have an update on this matter please?

jfversluis commented 2 years ago

No updates to share unfortunately

SimLeongChun commented 2 years ago

Hi,

I've the same issue on Xamarin Forms after updated from 5.0.0.2012 to 5.0.0.2478. @NicolaZuc, you have any solution? I think is due to Xamarin.Google.Android.Material.

SimLeongChun commented 2 years ago

Hi NicolaZuc,

I managed to solved it by removing Entry.Text = "" in OnFocus EventHandler. You may try it.

NicolaZuc commented 2 years ago

Hi NicolaZuc,

I managed to solved it by removing Entry.Text = "" in OnFocus EventHandler. You may try it.

Hi, that's something that u have on ur code because u wrote it, it can't work for me. Thanks anyway ;)

valentasm1 commented 2 years ago

@SimLeongChun I am also had issues when upgrading to 5.0.0.2478. We dont use any entry, we just catch key on OnKeyDown in MainActivity. Now it never returns new line symbol (end of barcode). Maybe do you have suggestions?

SimLeongChun commented 2 years ago

@SimLeongChun I am also had issues when upgrading to 5.0.0.2478. We dont use any entry, we just catch key on OnKeyDown in MainActivity. Now it never returns new line symbol (end of barcode). Maybe do you have suggestions?

I'm not sure on this since my issue is from barcode reader. But, you can try append "\n" or "\r\n" explicitly to add new line in your OnKeyDown Event.

valentasm1 commented 2 years ago

@SimLeongChun Barcode reader acts as keybourd and send barcode as char and when it end reads it sends new line char "\n". That new line is never trigered in event. Everything was fine before 5.0.0.2478. I am not focuses entry. Like no focus at all

SimLeongChun commented 2 years ago

@SimLeongChun Barcode reader acts as keybourd and send barcode as char and when it end reads it sends new line char "\n". That new line is never trigered in event. Everything was fine before 5.0.0.2478. I am not focuses entry. Like no focus at all

For my case, I had a OnFocused EventHandler with myEntry.Text = "", and this cause the issue. I solved it by comment out this line. Maybe you can try add OnFocus EventHandler. But I do add Task.Run(async () => {await Task.Delay(600); myEntry.Focus()});

You can refer to this link as reference: https://stackoverflow.com/questions/38240733/why-entrys-focus-method-isnt-working-from-pages-constructor

jkarnopp commented 2 years ago

I'm having the same issue. The barcode scanner acts as a keyboard wedge, and it sends a CRLF at the end of the scan. Sometimes it works properly, but it usually cuts a few characters off. When the completed event handler detects the CRLF, I use the EventToCommandBehavior to fire a command and pass a reference to the entry, but it's like the entry box didn't finish receiving the text when it detected the CRLF. Let's say you are scanning a barcode that represents 123456, it may only read 123 in the entry box. On the barcode scanner, I can turn off the terminating characters, then manually hit the enter key, and everything works fine. If there was some way to introduce a delay between when the event handler is triggered and the command is called, this would probably resolve the issue.

Here is what my XAML looks like for the entry:

<Entry 
    x:Name="ScanEntry"
    Text="{Binding ScanBoxText,Mode=TwoWay}"
    WidthRequest="350" 
    Placeholder="{Binding ScanBoxPlaceHolder}"
    >

    <Entry.Behaviors>
        <xct:EventToCommandBehavior 
        EventName="Completed" 
        Command="{Binding ScanBoxCompletedCommand}" 
        CommandParameter="{x:Reference ScanEntry}"/>
    </Entry.Behaviors>

    <Entry.Effects>
        <xct:LifecycleEffect Loaded="LifeCycleEffect_Loaded" />
    </Entry.Effects>
</Entry>
NicolaZuc commented 2 years ago

I'm having the same issue. The barcode scanner acts as a keyboard wedge, and it sends a CRLF at the end of the scan. Sometimes it works properly, but it usually cuts a few characters off. When the completed event handler detects the CRLF, I use the EventToCommandBehavior to fire a command and pass a reference to the entry, but it's like the entry box didn't finish receiving the text when it detected the CRLF. Let's say you are scanning a barcode that represents 123456, it may only read 123 in the entry box. On the barcode scanner, I can turn off the terminating characters, then manually hit the enter key, and everything works fine. If there was some way to introduce a delay between when the event handler is triggered and the command is called, this would probably resolve the issue.

Here is what my XAML looks like for the entry:

<Entry 
    x:Name="ScanEntry"
    Text="{Binding ScanBoxText,Mode=TwoWay}"
    WidthRequest="350" 
    Placeholder="{Binding ScanBoxPlaceHolder}"
    >

    <Entry.Behaviors>
        <xct:EventToCommandBehavior 
        EventName="Completed" 
        Command="{Binding ScanBoxCompletedCommand}" 
        CommandParameter="{x:Reference ScanEntry}"/>
    </Entry.Behaviors>

    <Entry.Effects>
        <xct:LifecycleEffect Loaded="LifeCycleEffect_Loaded" />
    </Entry.Effects>
</Entry>

Yeah that's exactly what i've reported, the only difference with me is that i've used the EntryReturnCommand instead of using a behavior on the completed event but the final purpose it's the same.