i have a button on my UI, and when the user makes a long click, i want to use a switch statement, but it doesn't work.
bool test = true;
button.LongClick += Button_LongClick;
private void Button_LongClick(object sender, Android.Views.View.LongClickEventArgs e)
{
switch (test)
{
case true:
// Toast error
break;
case false:
// call a method
break;
}
}
I don't know why but the switch is not working, the method is always called, even if the bool is true.
Did i missed something?
Yes,bool is a type,we should define a variable of booland assign a value to this variable.(eg. true or false).
For example ,you can use it like this:
bool flag = true;
button.LongClick += Button_LongClick;
private void Button_LongClick(object sender, Android.Views.View.LongClickEventArgs e)
{
switch (flag)
{
case true:
// Toast error
Toast.MakeText(this,"the value of flag is true. " ,ToastLength.Short).Show();
break;
case false:
// call a method
Toast.MakeText(this, "the value of flag is false. ", ToastLength.Short).Show();
break;
}
}
Related
I'm developing a kind of remote controller car.
I'm using a window CE device and Compact Framework 2.0 C#.
When Remote controller adjust the speed of car,
I'm using a sequential way like stairs.
However, It is sometimes going up and down 2 steps, 4 steps.
I would like to make only one step up and down from now step.
For example, now step is 4 then I just go to 3 or 5 not 8 or 1.
// Dealing with GPIO Input signal (detect push button)
private void smartGPIO1_EvtPortADatasChange(object sender, EventArgs e)
{
int iPortDatas;
SmartX.PORTDataEvtArgs PortDatas;
PortDatas = (SmartX.PORTDataEvtArgs)e;
iPortDatas = PortDatas.iPortDatas;
if (!test_start_Flag)
{
// User push the down button
if ((iPortDatas & 0x08) == 0x00)
{
motor_step = (motor_step <= -2) ? -2 : motor_step -= 1;
motor_handler(motor_step);
}
// User push the up button
if ((iPortDatas & 0x05) == 0x01)
{
motor_step = (motor_step >= 12) ? 12 : motor_step += 1;
motor_handler(motor_step);
}
}
}
// When button is pushed, send a command to car depends on the step
public int motor_handler(int step)
{
switch (step)
{
case 0:
// send command
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
break;
case -1:
break;
case -2:
break;
}
return step;
}
That code is for sure looped through on every update. Meaning that the single push of up or down button gets registered tens of times every second, so it seems like it goes more than one step at a time. You need to somehow register only new button presses.
//define something like this to the class level
Bool downIsPressed;
Bool upIsPressed;
//and then check and modify those values
if ((iPortDatas & 0x08) == 0x00 && downIsPressed == false)
{
motor_step = (motor_step <= -2) ? -2 : motor_step -= 1;
motor_handler(motor_step);
downIsPressed = true;
}
else
{
downIsPressed = false;
}
That should only register the button once and enable it once the button is released. There might be some cleaner and nicer looking way too, but hope that is of some help :)
Is it Recursive?
motor_handler(motor_step);
Calls private void smartGPIO1_EvtPortADatasChange(object sender, EventArgs e)
That's why each button push you get two steps.
The solution is a Private Boolean, typically I name IsRecursive:
class RacingCar {
private bool IsRecursive = false;
private void smartGPIO1_EvtPortADatasChange(object sender, EventArgs e)
{
if (IsRecursive) return;
IsRecursive = true;
....
IsRecursive = false;
}
}
Your code only ever increments or decrements the motor_step by 1 so if you're finding that the variable value jumps up by 2 etc then the code must have run twice in quick succession.
You have to find a way to "debounce" two events arriving at the same time. For example, when you step, record the current time. If the next event occurs less than one second since the previous event, ignore the event
//declare var and set to min value
private DateTime last_event_time = DateTime.MinValue;
private void smartGPIO1_EvtPortADatasChange(object sender, EventArgs e)
{
//debounce
if((DateTime.Now - last_event_time).TotalSeconds < 1)
return;
last_event_time = DateTime.Now;
int iPortDatas;
SmartX.PORTDataEvtArgs PortDatas;
Note: I've no idea if using DateTime will work on your platform, please take this code as pseudocode to demonstrate the concept
Debouncing like this will rely on the fact that the math on the time now vs time then needs to execute faster than events happen
If you want it to be so that step never changes as long as the button is held down you need to flip the logic around a bit so that as long as events keep arriving quickly, the code keeps returning - for that. You would update the time every time you return and only let the code proceed if more than X time has passed since the last event arrived
Im creating a Hotkey funtion atm so users can adjust Keybindings to their own needs, before i set the keys and they were not adjustable. This is what i used before.
public void gHook_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.D:
// stuff
Salvagebtn.PerformClick();
break;
case Keys.F12:
// stuff
pausebtn.PerformClick();
break;
case Keys.K:
//stuff
Geardropbtn.PerformClick();
break;
case Keys.F:
//stuff
Gamblebtn.PerformClick();
break;
case Keys.A:
//stuff
LeftClickSpambtn.PerformClick();
break;
case Keys.H:
// stuff
openGRbtn.PerformClick();
break;
case Keys.B:
//stuff
gemupbtn.PerformClick();
break;
}
}
Now i made a setting Tab where ppl can change Keybindings which looks like this.
How can i get it going that instead of the "case Keys.D:" it will react to the Keybinding in the Textbox ?
A few ways to do it. One way you could go would be to assign the keybindings to a Dictionary where UserActions is an enum defining the possible action:
public enum UserAction
{
Salvage, Pause, Drop // etc...
}
Then when the user presses a key, something like:
public void gHook_KeyDown(object sender, KeyEventArgs e)
{
string k = e.KeyCode.ToString();
if (KeyBindings.Contains(k)) //KeyBindings is your field or variable which is a Dictionary<string, UserAction>
{
var action = KeyBindings[k]
switch (action)
{
case UserAction.Salvage:
// stuff
Salvagebtn.PerformClick();
break;
case UserAction.Pause:
// stuff
pausebtn.PerformClick();
break;
// and so on...
Assigning values to the dictionary:
var KeyBindings = new Dictionary<string, UserAction>;
KeyBindings["D"] = UserAction.Salvage;
KeyBindings["A"] = UserAction.Pause;
If you need to get a key from the user's input, you can use Enum.TryParse(input):
Keys key;
if (Enum.TryParse<Keys>(textBoxSalvage.Text, out key))
{
KeyBinding[textBoxSalvage.Text] = UserAction.Salvage; // note that 'UserAction.something' comes from the context
}
If I have an Enum as follows:
private object myEnumValLock = new object();
private MyEnum _myEnumVal;
public MyEnum MyEnumVal
{
get
{
lock(this.myEnumValLock)
{
return this._myEnumVal;
}
}
set
{
lock(this.myEnumValLock)
{
if (value != this._myEnumVal)
{
this.HandleNewMyEnumVal(this._myEnumVal, value);
this._myEnumVal = value;
}
}
}
}
When using switch case, can I directly use the property like this:
private void MyFunc()
{
switch (this.MyEnumVal)
{
case MyEnum.First:
// Do Something
break;
case MyEnum.Second:
// Do Something
break;
}
}
Or should I read it first and then use switch on the read value like this:
private void MyFunc()
{
var myEnumVal = this.MyEnumVal;
switch (myEnumVal)
{
case MyEnum.First:
// Do Something
break;
case MyEnum.Second:
// Do Something
break;
}
}
If using if ... else as in this question, I'd need to read the value first. Is it the same case with switch statement? What is the behaviour of the switch statement? Does it read the value at every case statement or reads only once at the beginning?
As #mjwills suggested, I put a breakpoint in the getter and it got hit only once at the beginning of the switch statement. I can't find any specific reference where it says the switch statement reads the value only once (please comment if you find the reference). But the breakpoint does prove it.
So, although you need to have read the value beforehand in case of if ... else, in case of the switch statement, you don't need to.
This question already has answers here:
Is async always asynchronous in C#? [duplicate]
(1 answer)
Do you have to put Task.Run in a method to make it async?
(3 answers)
async method in C# not asynchronous?
(3 answers)
Closed 5 years ago.
I have a TextBox with a TextChanged event that calls a custom event if the text of the textbox represents an existing file. In this event, there is a call to an outside dll that does some processing on the File, which can take upwards of a minute to finish. There is also some post-processing I do, dependent on what result this method returns to me. Currently, this is blocking my UI, which is highly undesirable.
There are essentially 2 "options"/scenarios I see.
Within the custom event, somehow wait for the dll call to finish, before continuing the event, while also keeping the UI free. This seems like the simplest idea from my multithreading-untrained self, but it also conceptually throws red flags at me: Is this even possible given that the custom event itself (called from TextChanged) is on the UI thread?
Throw the entire custom event into it's own thread using Task.Run(). Downside here is that apart from the dll method call, there is quite a good amount of UI elements that are affected by getters/setters after the long method. I could write alternated getters/setters based on the appropriate InvokeRequired, but if there is a more correct way to do this, I'd rather take that approach.
I made a much shorter (although contrived) example project, which shows essentially what I'm after, using option 2 from above:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1.Items.Add("Select One...");
comboBox1.Items.Add("Item 1");
comboBox1.Items.Add("Item 2");
Value = 0;
}
public string SetMessage
{
set
{
if (lblInfo.InvokeRequired)
lblInfo.BeginInvoke((MethodInvoker)delegate () { lblInfo.Text = Important ? value + "!" : value; });
else
lblInfo.Text = Important ? value + "!" : value;
}
}
public bool Important
{
get
{
return chkImportant.Checked;
}
set
{
if (chkImportant.InvokeRequired)
chkImportant.BeginInvoke((MethodInvoker) delegate() { chkImportant.Checked = value; });
else
chkImportant.Checked = value;
}
}
public SomeValue Value
{
get
{
if (comboBox1.InvokeRequired)
{
SomeValue v = (SomeValue)comboBox1.Invoke(new Func<SomeValue>(() => SomeValue.Bar));
return v;
}
else
{
switch (comboBox1.SelectedIndex)
{
case 1:
return SomeValue.Foo;
case 2:
return SomeValue.Bar;
default:
return SomeValue.Nothing;
}
}
}
set
{
if (comboBox1.InvokeRequired)
{
comboBox1.BeginInvoke((MethodInvoker)delegate ()
{
switch (value)
{
case SomeValue.Nothing:
comboBox1.SelectedIndex = 0;
break;
case SomeValue.Foo:
comboBox1.SelectedIndex = 1;
break;
case SomeValue.Bar:
comboBox1.SelectedIndex = 2;
break;
}
});
}
else
{
switch (value)
{
case SomeValue.Nothing:
comboBox1.SelectedIndex = 0;
break;
case SomeValue.Foo:
comboBox1.SelectedIndex = 1;
break;
case SomeValue.Bar:
comboBox1.SelectedIndex = 2;
break;
}
}
}
}
private void CustomEvent(object sender, EventArgs e)
{
if (!Important)
Important = true;
SetMessage = "Doing some stuff";
if (Value == SomeValue.Foo)
Debug.WriteLine("Foo selected");
//I don't want to continue until a result is returned,
//but I don't want to block UI either.
if (ReturnsTrueEventually())
{
Debug.WriteLine("True!");
}
Important = false;
SetMessage = "Finished.";
}
public bool ReturnsTrueEventually()
{
//Simulates some long running method call in a dll.
//In reality, I would interpret an integer and return
//an appropriate T/F value based on it.
Thread.Sleep(5000);
return true;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
//Do I *need* to multithread the whole thing?
Task.Run(() => CustomEvent(this, new EventArgs()));
}
}
public enum SomeValue
{
Nothing = 0,
Foo = 100,
Bar = 200
}
Note: I'm not asking for code review on my option 2 code. Rather, I'm asking if option 2 is necessary to accomplish, since that option causes me to change a considerably larger portion of code, given that it's only 1 method within it holding up the entire process.
I also realize I can simplify some of the code in these properties to prevent replication. For the sake of demonstrating to myself and debugging, I am holding off on that at this time.
Here is what I had related to option 1 (left out duplicate code and the getters/setters without their invokes):
private async void CustomEvent(object sender, EventArgs e)
{
if (!Important)
Important = true;
SetMessage = "Doing some stuff";
if (Value == SomeValue.Foo)
Debug.WriteLine("Foo selected");
//I don't want to continue until a result is returned,
//but I don't want to block UI either.
if (await ReturnsTrueEventually())
{
Debug.WriteLine("True!");
}
Important = false;
SetMessage = "Finished.";
}
public async Task<bool> ReturnsTrueEventually()
{
//Simulates some long running method call in a dll.
//In reality, I would interpret an integer and
//return an appropriate T/F value based on it.
Thread.Sleep(5000);
return true;
}
This is basically what you want. I'm violating a couple best-practices here, but just showing it's not that complicated. One thing to keep in mind is that the user can now click this button multiple times in a row. You might consider disabling it before processing. Or you can do a Monitor.TryEnter() to make sure it's not already running.
private async void buttonProcess_Click(object sender, RoutedEventArgs e)
{
textBlockStatus.Text = "Processing...";
bool processed = await Task.Run(() => SlowRunningTask());
}
private bool SlowRunningTask()
{
Thread.Sleep(5000);
return true;
}
And I'm doing some exercises about switch. I just did it from console application and I would like to do it in window forms applications. I'm looking for syntax on how to do switch in window forms.
In console it's usually like this:
switch (wordValue)
{
case 1:
Console.WriteLine("You have entered numbered two");
break;
default:
break;
how can I do this in my window forms, if I would like to display this cases in listbox1?
Thanks
=======
Thank you. I tried this one but I'm getting an error. This is what I've tried:
public static void WriteNumber(int wordValue)
{
switch (wordValue)
{
case 1:
listbox.Items.Add("You have entered number one");
break;
}
}
========
This is the code I'm trying to do:
private void btnOk_Click(object sender, EventArgs e)
{
string strUserInputNumber;
strUserInputNumber = textBox1.Text.Trim();
Int32 intNumber;
if (Int32.TryParse(textBox1.Text, out intNumber))
{
listBox1.Items.Add(intNumber.ToString());
}
}
public static void WriteNumber(int wordValue)
{
switch (wordValue)
{
case 1:
this.listBox1.Items.Add("You have entered numbered one");
break;
}
}
====
This is the new code:
private void btnOk_Click(object sender, EventArgs e)
{
string strUserInputNumber;
strUserInputNumber = textBox1.Text.Trim();
Int32 intNumber;
if (Int32.TryParse(textBox1.Text, out intNumber))
{
listBox1.Items.Add(intNumber.ToString());
WriteNumber(intNumber);
}
else
{
MessageBox.Show("Please enter an integer not a character");
}
}
public void WriteNumber(int wordValue)
{
switch (wordValue)
{
case 1:
listBox2.Items.Add("You have entered numbered one");
break;
case 2:
listBox2.Items.Add("You have entered numbered two");
break;
case 3:
listBox2.Items.Add("You have entered numbered three");
break;
default:
listBox2.Items.Add("You have exceeded the range of 1-3. Please enter the number between 1-3");
break;
}
The switch/case syntax is identical between WinForms and a console app (or any other type of application or class library), the only difference is how you display the data. If you want to add a string to a listbox (which is apparently what you're asking), it's as simple as
listBox1.Items.Add("Here is the text of the list box item");
This should work:
public void WriteNumber(int wordValue)
{
switch (wordValue)
{
case 1:
listbox.Items.Add("You have entered number one"); break;
}
}
You need to remove the static keyword to get access to the listbox, which is an instance variable.
This works fine:
switch (wordValue)
{
case 1:
this.listBox1.Items.Add("You have entered numbered two");
break;
default:
break;
}