Device.StartTimer equivalent in Native Xamarin - c#

I'm working on an application that simulates an old phone keypad like the ones in a Nokia 3310 where multiple button clicks changes the letter thats being written from 1 to A, B, etc.
I've originally built the application in Xamarin Forms but the assignment needs it to be in Native Xamarin so I need to pass it there. The original code I used in Xamarin forms was the following:
private void Button_Clicked(object sender, EventArgs e)
{
if (ButtonCount < 1)
{
TimeSpan tt = new TimeSpan(0, 0, 1);
Device.StartTimer(tt, NumberofClicks);
}
ButtonCount++;
}
With the NumberofClicks method being the following:
bool NumberofClicks()
{
if (ButtonCount > 1)
{
//Event for 2 button clicks
}
else
{
//Event for 1 button click
}
ButtonCount = 0;
return false;
Since Xamarin Native supports applying tags to buttons I want to try and make a method for all the buttons to be more efficient where it uses the tag it has, for this purpose I use the expression of var Btn = ((Android.Widget.Button)btnPresionado) so I can simply use Btn.Tag.ToString() when adding it to text. As for what I tried to use as a Device.StarTimer equivalent, I used a System.Threading.Timer as seen in the following code:
public void ButtonClick(object btnPresionado, EventArgs e)
{
if (ButtonCount < 1)
{
System.Threading.Timer timer = new Timer(NumberofClicks,btnPresionado, 2000, Infinite);
}
ButtonCount++;
}
public void NumberofClicks(object btnPresionado)
{
var Btn = ((Android.Widget.Button)btnPresionado);
if (ButtonCount > 1)
{
//Double click event
}
else
{
//Single click event
}
ButtonCount = 0;
}
Unfortunately when testing this, it does not work and makes the app crash in the emulator (I cant see what exactly goes wrong since this is a 3rd party emulator because Hyper-V simply refuses to install itself on my PC at the moment) so I want to ask what would be a good equivalent for Device.StartTimer() or what exactly am I doing wrong here?
Thank you

Related

Unable to handle a button click event in SAP B1 UI API

I'm starting with SAP B1 UI API (9.0) and I'm trying to handle a button click without any luck so far. This is how I'm doing it (removing unnecessary to make it shorter):
static void Main(string[] args)
{
SetApplication(args);
var cParams = (FormCreationParams)App.CreateObject(BoCreatableObjectType.cot_FormCreationParams);
cParams.UniqueID = "MainForm_";
cParams.BorderStyle = BoFormBorderStyle.fbs_Sizable;
_form = App.Forms.AddEx(cParams);
/*Setting form's title, left, top, width and height*/
// Button
var item = _form.Items.Add("BtnClickMe", BoFormItemTypes.it_BUTTON);
/*Setting button's left, top, width and height*/
var btn = (Button)item.Specific;
btn.Caption = "Click Me";
_form.VisibleEx = true;
App.ItemEvent += new _IApplicationEvents_ItemEventEventHandler(App_ItemEvent);
}
private static void SetApplication(string[] args)
{
string connectionString = args[0];
int appId = -1;
try
{
var guiApi = new SboGuiApi();
guiApi.Connect(connectionString);
App = guiApi.GetApplication(appId);
}
catch (Exception e)
{ /*Notify error and exit*/ }
}
private static void App_ItemEvent(string FormUID, ref ItemEvent pVal, out bool BubbleEvent)
{
BubbleEvent = true;
if (FormUID == "MainForm_" && pVal.EventType == BoEventTypes.et_CLICK &&
pVal.BeforeAction && pVal.ItemUID == "BtnClickMe")
{
App.MessageBox("You just click on me!");
}
}
When I click the button nothing happens, is this the way to go? I've made so many variations in the handler method but nothing yet. Another detail is that the visual studio's debugger terminates as soon as the addon is started (maybe this has something to do with my problem).
I hope you can help me. Thanks in advance.
David.
Since the application stops running there are two possible answers to this question depending on what you prefer to use.
If you are using the SAPbouiCOM library you need a way to keep the application running, the way I use is the System.Windows.Forms.Application.Run(); from the windows forms assembly.
If you are using the SAPBusinessOneSDK and SAPbouiCOM.Framework as a reference you can use the App.Run();.
Both of these need to be invoked as soon as your setup code has run.

Wait for x seconds in while loop c#

Im trying to make a simple application to learn some things in c# (Visual Studio).
For now i am building a music player, and one of the actions is fading out the music at the button click event.
I've got no problem with building a fade-out part, i made a while loop and put the volume down with 1% eacht time the loop is running. Also i update a label with the fade value.
Only problem is, for slowing down the fading i'm using the Thread.Sleep event, and that part is freezing my application, and also is blocking any updates to my text label with the fade value.
The fading is working fine, so the only part I have to work on is another option to build some delay in. On some topics over here i did read about the timer, and i added a timer component in Visual Studio. Only problem, I am new to c# and don't know how to use it correctly in this while loop.
Can anybody give me some help?
The current code is:
private void BtnPodiumtune1Fadeout_Click(object sender, EventArgs e)
{
PlayerPodiumtune1.settings.volume = 100;
fade1 = 100;
while (fade1 != -1)
{
PlayerPodiumtune1.settings.volume = fade1;
Fadelevel1.Text = fade1.ToString();
System.Threading.Thread.Sleep(30);
fade1 = fade1 - 1;
}
PlayerPodiumtune1.Ctlcontrols.stop();
}
You could use a pattern like this instead of a timer. A timer is a fine way to go, just throwing this option out there:
private async void button_Click(object sender, EventArgs e)
{
if (Monitor.TryEnter(sender))
{
int fade1 = 1000;
while (fade1 != -1)
{
await Task.Delay(30);
fade1--;
}
}
}
So sender is the button, and Monitor.TryEnter prevents the function from being run again until the function is done. async tells the framework that this function can be executed asynchronously and is necessary for await. await returns control of the thread to the UI until the task is done.
PS--You're going to need something like Monitor.TryEnter to prevent re-entrancy in a timer-based solution as well, by the way.
This is a Console Application in C#:
using System;
namespace WaitAsync
{
class Program
{
static void Main(string[] args)
{
bool ok = false;
Console.Write("EnterTime (Seconds): ");
int time = Convert.ToInt32(Console.ReadLine()) * 1000;
while (ok != true)
{
System.Threading.Thread.Sleep(time);
ok = true;
Console.WriteLine("Waiting Time Just Finished");
}
Console.ReadLine();
}
}
}

C# wait for timer to end before starting an other timer

Hi I'm making a UI in Windform and using timers. It's all quite new to me so my understanding of it is kinda of weak. I use timers to make a side menu animation.
The 1st timer is to show the menu. Something like this :
private void ShowFullToolsTimer_Tick(object sender, EventArgs e)
{
FonctionsNatives.dessinerOpenGL();
if (editionToolsMenu.Width >= 200)
ShowFullTools.Stop();
else
editionToolsMenu.Width += 5;
}
And to hide the side menu I have something similar :
private void HideFullMenu_Tick(object sender, EventArgs e)
{
if (editionToolsMenu.Width > 0)
editionToolsMenu.Width -= 5;
else
HideFullMenu.Stop();
}
The probleme I have is that I want one animation to be COMPLETELY over before starting the other one. I've been using Application.DoEvent(); if the timer.Enable is true, but i'm aware that it's terrible to do that and causes even more bugs. Any solutions?
EDIT1: Sorry for not being precise. Both timer start when a diffrent component is clicked. I also cant write both of the to end, for example:
ShowfullMenu.Start():
HideFullMenu.Start();
Since one does += and the other does -=. They'll be stuck in an infinite loop. Putting the thread to sleep stops the whole UI.
Stop the other timer when you are animating one menu and then restart it once you are done animating (and vice-versa). Here is some non tested code:
private void ShowFullToolsTimer_Tick(object sender, EventArgs e)
{
FonctionsNatives.dessinerOpenGL();
if (editionToolsMenu.Width >= 200)
{
ShowFullTools.Stop();
// start the other one
HideFullMenu.Start();
}
else
{
editionToolsMenu.Width += 5;
if (HideFullMenu.Enabled)
{
HideFullMenu.Stop();
}
}
}

Let user start typing when winform pops up without them having to click on the textbox

I am working on a barcode reader project in Visual Studio using C#. I have created a WinForm Application and have added a RichTextBox to it. I want the user to be able to start scanning when they open the program without having to click on the textbox.
Thanks in advance!
(I'm assuming you have an application with a multitude of stuff in it. However there is one field that needs to be filled in with a scanned barcode.)
I faced a simular issue a while ago. I needed to capture a barcode in WPF. Setting the focus property in load seemed a good idea but because there were a multitude of other controls on the page that the user could click etc. focus jumped from one control to the other, making the barcode go in the wrong fields or vanish in a grid that has focus for example.
We were not able to use any other way of reading the barcode from the scanner because it was used for other applications too. It had to be configured as input.
We came up with a solution of capturing the keypresses instead.
By using the keydown events we could track the scanner input and stated that if more than 5 keys came in within a limited time + with our prefix and suffix it had to be a barcode.
EDIT: here is a simplified version of the class.
public delegate void BarcodeRead(string barcode);
public class ManualReader
{
private string barcode = "no barcode detected";
private string possible = "";
private DateTime timestarted = DateTime.MinValue;
private Timer InputTimeout;
public BarcodeRead OnBarcodeRead;
public void OnKeyDown(object sender, KeyEventArgs.KeyEventArgs e)
{
//create timer if it does not exist
if (InputTimeout == null)
{
InputTimeout = new Timer(100);
InputTimeout.Enabled = true;
InputTimeout.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}
//reset timer
InputTimeout.Stop();
InputTimeout.Start();
//possible barcode
possible += CharToKey.GetCharFromKey(e);
if (timestarted == DateTime.MinValue)
{
timestarted = DateTime.Now;
}
}
//Timer elapses
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
//Is it a barcode?
if ((timestarted.AddMilliseconds(600) > DateTime.Now) && (possible.Length > 5)
&& (timestarted != DateTime.MinValue) && possible.Contains("\r"))
{
barcode = possible;
barcode = barcode.Remove(0, 1);
barcode = barcode.Replace("\r", "");
//launch delegate
if (OnBarcodeRead != null)
{
OnBarcodeRead.Invoke(barcode);
}
}
//delete timers
timestarted = DateTime.MinValue;
InputTimeout.Dispose();
InputTimeout = null;
possible = null;
}
}
}
I'm aware that for really short timeouts datetime functions aren't precise but still this little 'hack' worked perfectly for our application.
You can add directly in the element. This works for textbox but not sure with RichTexBox
FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"

Windows Phone 8 canĀ“t call AudioVideoCaptureDevice second time

In my App you can open a Site where you can switch on and off the Flashlight.
The first time it works, but if I try to switch the flashlight on a second time the App crashes.
I think this is a Problem with AudioVideoCaptureDevice.OpenAsync. If I call it a second time the App crashes with a System.Reflection.TargetInvocationException WinRT-Informationen: Unable to acquire the camera. You can only use this class while in the foreground.
Someone know this Problem?
protected AudioVideoCaptureDevice Device { get; set; }
public Page10()
{
InitializeComponent();
}
async void tglSwitch_Checked(object sender, RoutedEventArgs e)
{
var sensorLocation = CameraSensorLocation.Back;
if (this.Device == null)
{
// get the AudioVideoCaptureDevice
this.Device = await AudioVideoCaptureDevice.OpenAsync(sensorLocation,
AudioVideoCaptureDevice.GetAvailableCaptureResolutions(sensorLocation).First());
}
var supportedCameraModes = AudioVideoCaptureDevice
.GetSupportedPropertyValues(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchMode);
if (supportedCameraModes.ToList().Contains((UInt32)VideoTorchMode.On))
{
this.Device.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.On);
// set flash power to maxinum
this.Device.SetProperty(KnownCameraAudioVideoProperties.VideoTorchPower,
AudioVideoCaptureDevice.GetSupportedPropertyRange(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchPower).Max);
this.tglSwitch.Content = "Light on";
this.tglSwitch.SwitchForeground = new SolidColorBrush(Colors.Green);
}
}
void tglSwitch_Unchecked(object sender, RoutedEventArgs e)
{
var sensorLocation = CameraSensorLocation.Back;
sensorLocation = CameraSensorLocation.Back;
var supportedCameraModes = AudioVideoCaptureDevice
.GetSupportedPropertyValues(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchMode);
if (this.Device != null && supportedCameraModes.ToList().Contains((UInt32)VideoTorchMode.Off))
{
this.Device.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.Off);
this.tglSwitch.Content = "Light off";
}
}
I would recommend to initialize the camera with OpenAsync ONE TIME in page lifecycle, for example in OnNavigatedTo event. And only makeSetProperty() methods calls code in your checkbox events to control light. It is also very important to dispose camera correctly then leaving the page, for example in OnNavigatedFrom event, by calling device.Dispose(). This option also make your flashlight to work faster.
Keep in mind that Windows Phone 8.1 now has dedicated API for torch, which works great and the code is more beautiful. You can use in Silverlight project as well, but you have to migrate your project. Here is more about this http://developer.nokia.com/community/wiki/Using_the_camera_light_in_Windows_Phone_7,_8_and_8.1 and https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.devices.torchcontrol.

Categories