How to keep update user interface on Windows Phone apps responsively - c#

I am trying to create an Calculator app on WP 8.1. I would like to create an Automation Button which perform automation click on other buttons of my app. For example, in this code, when I click the automation button, it will call the event of clicking other buttons such as:
private void Auto_Click(object sender, RoutedEventArgs e)
{
button3_Click(this, null);
button_addition_Click(this, null);
button7_Click(this, null);
button_result_Click(this, null);
}
I this example, I perform the operations is "3 + 7" and after that I press the "Equal" button.
The result created is right. But I have 1 issue, that is the showing of textbox's data don't change responsively in this method. But when I click the button3 independently, the showing of textbox's data changed instantly. The code button3_Click event is:
private void button3_Click(object sender, RoutedEventArgs e)
{
if (is_subtend(this.textbox.Text) == false)
this.textbox.Text += "3";
else
this.textbox.Text = "3";
}
So what can I do to change the showing of textbox's data in the automation_click event.
Thank you for your help.

The results are as expected. There are really no delays in between those Button Clicks, so it changes the text really fast, no time for the UI to update. If you want to see a "3" then... a "3+"... then a "3+7"... etc.. then implement a delay in-between the button clicks.
To see what I mean try this
using System.Threading.Tasks;
// don't forget the async
private async void Auto_Click(object sender, RoutedEventArgs e)
{
button3_Click(this, null);
await Task.Delay(TimeSpan.FromMilliseconds(250));
button_addition_Click(this, null);
await Task.Delay(TimeSpan.FromMilliseconds(250));
button7_Click(this, null);
await Task.Delay(TimeSpan.FromMilliseconds(250));
button_result_Click(this, null);
await Task.Delay(TimeSpan.FromMilliseconds(250));
}
Lower the 250 to a value you want for the speed you're looking for.

Related

Is there a way to call a function after button is pressed?

So my problem is the following:
I have a button, which has a set background. If the button is pressed, I call the function, which is called check();
The problem is, that if the button is pressed, I will set the background to a certain picture, and if I call the fucntion check, and in that check, sometimes I delete the background.
So sometimes without even seeing the background it gets deleted. How can I improve it, so it gets deleted only like after 3-4 seconds?
private void button2_Click(object sender, EventArgs e)
{
Image img = Image.FromFile(#"C:\Users\nhorv\Downloads\javascript.jpg");
button2.BackgroundImage = img;
buttonList.Add(button2);
counter++;
check();
}
This is the button_click function, and this is the check() func:
void check()
{
if (counter == 2)
{
if (buttonList.Contains(button1) && buttonList.Contains(button6))
{
progressBar1.Increment(10);
}
.
.
.
else
{
buttonList[0].BackgroundImage = null;
buttonList[1].BackgroundImage = null;
}
buttonList.Clear();
counter = 0;
}
}
The buttons are stored in the buttonList list.
For the timing, I heard about: System.Threading.Thread.Sleep(1000); - for a 1 second delay.
Any help is really appreciated!
Edit:
The problem is with the buttons. If I call the button1_pressed function, it runs trough and only after that is the background changed. Unfortunately, there is the check function, which immediately deletes the background. So I have to somehow make the check function after the button press, so that the button can change the background, and only after that will I call check();
Use
System.Threading.Thread.Sleep(3000);
to pause the execution for 3 seconds and then delete the background based on the condition.
private void button2_Click(object sender, EventArgs e)
{
Image img = Image.FromFile(#"C:\Users\nhorv\Downloads\javascript.jpg");
button2.BackgroundImage = img;
buttonList.Add(button2);
System.Threading.Thread.Sleep(3000);
check();
}
So this is what I have understood from your code: you have button 2 with the event handler button2_Click associated on it.
Once you have clicked button 2, you set the background image to the button, add the BUTTON 2 to a list of button, increment a variable called counter by 1 and then call check function.
Check function, first of all, controls if counter is 2. If not, exit. Else, controls if button1 and button6, that I don't know where they're and if thery're added to to buttonList or not, are into the list or not. If they both are present, then increment the progressbar by 10. If one of them is not in the list, or both, you set the background immage of the first 2 buttons in the buttonList to null...
In the end, you clear the buttonList and set the counter to 0.
First of all, we should see the entire code in order to understand what's going on. Relying only on what I can see, start the programm in debug mode and check if button1 and button6 are in the list. In my opinion, you never add those 2 buttons to the list (is enough that only one of them is not present, since there's an and into the if), so the program will always delete the background image.
If I understand you correctly, you want to delay the check() function that deletes the background. You will need to create a thread that will do that:
async Task check()
{
if (counter == 2)
{
await Task.Delay(3000);
...<your other code>
}
}
Your button click then becomes:
private async void button2_Click(object sender, EventArgs e)
An you call your check method:
_ = check();
To create a small delay (so the player can check if they match, you should go for the async method)
But you need to prevent that, when the Task.Delay is running, a button is disabled. The await Delay ensures that the paint messages are handled, but also new buttons can be clicked.
Here an example:
private bool _buttonsEnabled = true;
private async void button2_Click(object sender, EventArgs e)
{
if(!_buttonsEnabled)
return;
_buttonsEnabled = false;
Image img = Image.FromFile(#"C:\Users\nhorv\Downloads\javascript.jpg");
button2.BackgroundImage = img;
buttonList.Add(button2);
counter++;
await check();
_buttonsEnabled = true;
}
private async Task check()
{
if (counter == 2)
{
if (buttonList.Contains(button1) && buttonList.Contains(button6))
{
progressBar1.Increment(10);
}
.
.
.
else
{
// wait for a second before clearing the background.
await Task.Delay(1000);
buttonList[0].BackgroundImage = null;
buttonList[1].BackgroundImage = null;
}
buttonList.Clear();
counter = 0;
}
}
You could set up a timer (see https://learn.microsoft.com/dotnet/api/system.windows.forms.timer) after the second button was pressed and reset the button images in the event handler of elapsed timer. (event is named Tick)

how to disable Application Bar Icon Button while processing other functions in windows phone application

reference
I have a code like below
private void btnSave_Click(object sender, EventArgs e){
(ApplicationBar.Buttons[0] as ApplicationBarIconButton).IsEnabled = false;
if (backstatus == false)
{
backstatus = true;
myPopup.IsOpen = true;
Dispatcher.BeginInvoke(delegate()
{
// some big code which take five minits to execute
}
} }
At the time of taping that button it is in enable mode. It will disable after execute hole the function.
But i need to disable it while processing other functions.
You can use MVVM way and bind commands from your viewmodel to the applicationbar buttons. Or else, use await async for the long process instead of dispatcher.begininvoke()

UI responsiveness on listbox ItemSelectionChanged() event

I'd like to enable a button if some Data is available:
private void myListBox_ItemSelectionChanged(object sender, EventArgs e)
{
downloadButton.Enabled = myList.SelectedItems.Cast<myClass.myObject>().Any(x => x.Data != null);
}
The problem is that the UI is not quite responsive, and behaves weirdly (sometimes when I click the selection does not get changed when I click and select a different element). I figured that this is because of that bit of code.
Any suggestion to speed things up?

Can not click button when a method running

private void AddMyScrollEventHandlers()
{
VScrollBar vScrollBar1 = new VScrollBar();
}
private void button1_Click(object sender, EventArgs e)
{
while (true)
{
if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
vScrollBar1.Value = vScrollBar1.Value + 1;
label1.Text = vScrollBar1.Value.ToString();
}
else
{
break;
}
System.Threading.Thread.Sleep(200);
}
}
private void button2_Click(object sender, EventArgs e)
{
// vScrollBar1.Scroll
}
I am new in C#. I was working on scroll. What I wanted here is, if anyone click button1 then scroll automatically move to the end and I wanted to show gradual value in label1. Also when someone click button2 scrolling stop.
Now the problem is label1 do not show gradual change in value. It shows value once when the scrolling stop.
Also when scrolling continue i,e when while loop is working I can not click on button2. Actually I can not click on the form even.
Someone please give me some idea how to do this.
This happens because the thread that is performing the task is busy, and it's the same thread that updates the UI. You can use a multithreading solution. Take a look at
BackgroundWorker
All the UI events run in the main thread of the application, so the application can only process one event at a time. When the application is processing an event, no other event will be processed.
Since you are doing a UI related work periodically, the best option is to use the Timer class:
Drop Timer from the toolbox into the form.
In the properties window, set the interval to 200.
Double click the timer object to create the Tick event handler.
Put this code in the newly created timer1_Tick method:
if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
vScrollBar1.Value = vScrollBar1.Value + 1;
label1.Text = vScrollBar1.Value.ToString();
}
else
{
timer1.Stop();
}
Change your methods as below:
private void AddMyScrollEventHandlers()
{
timer1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Stop();
}
Now you're done.
I would recommend using BackgroundWorker control, as suggested by Agustin Meriles. However, one more important thing to note is that You should use Control.Invoke(...) method to update controls from another thread.
I've modified Your code, tested it in a sample application and it seems to work correctly.
First, add a new BackgroundWorker control to Your form and assign backgroundWorker1_DoWork to its DoWork event.
Then, You can use the code below:
private void button1_Click(object sender, EventArgs e)
{
//code from here is moved to BackgroundWorker control
backgroundWorker1.RunWorkerAsync();
}
private void button2_Click(object sender, EventArgs e)
{
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//while (true)
//the condition directly in the while looks more clear to me
while (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
//update controls using Invoke method and anonymous functions
vScrollBar1.Invoke((MethodInvoker)delegate() { vScrollBar1.Value += 1; });
label1.Invoke((MethodInvoker)delegate() { label1.Text = vScrollBar1.Value.ToString(); });
//when called inside BackgroundWorker, this sleeps the background thread,
//so UI should be responsive now
System.Threading.Thread.Sleep(200);
}
}
If You have any problems when using this code, please let me know.
Update
As mentioned in the comments, You could also use ProgressChanged event of the BackgroundWorker. It requires some more changes in the code, but is more suitable in this case. You can find some information about it here: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx.
If You are not going to add any other code with more processing in the while loop, You can also use Timer control, as suggested by MD.Unicorn in his answer.

Monotouch TouchUpInside does not work, TouchDown works

I have seen some topics about this subject in Objective-C. I read a lot of them, spent 2 days on it on trying to find a solution and none of them worked for me. I am mainly coding in C#. Since my problem behaviour (fire only when leaving/re-enter button) and context (C#) is a bit different. So, I will try my chance by asking my question here.
I will try to keep it simple.
Here is a sample of code:
private UIButton _buttonTest;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
_buttonTest = new UIButton(new RectangleF(10, 70, 50, 50));
_buttonTest.SetTitle("0", UIControlState.Normal);
_buttonTest.TouchUpInside += HandleButtonTestTouchUpInside;
_buttonTest.BackgroundColor = UIColor.Red;
this.View.AddSubview(_buttonTest);
}
void HandleButtonTestTouchUpInside (object sender, EventArgs e)
{
string textNumber = _buttonTest.Title(UIControlState.Normal);
// Increment Number
_buttonTest.SetTitle((int.Parse(textNumber)+1).ToString(), UIControlState.Normal);
}
There is a button and the title text is set to "0".
When the user click on it, it increments the number (title) by 1.
This code usually works very well!
However, it does not work in some of my classes for some unknown reasons...
Here is the problem:
TouchUpInside does not fire. ... However, if I hold the button with a finger and keep holding the finger while leaving the button and then re-entering the button then release the button, then.... it will fire the TouchUpInside, .... so the finger need to leave and re-renter the button while holding the button to make the TouchUpInside fires. Usually, this code works very well.
Things Checked:
if I replace TouchUpInside by TouchDown, then TouchDown works.
'User Interaction Enabled' is set to True for all superviews.
All views frames (among the superviews) seem to be inside their superview frames.
I moved the _buttonTest around and I noticed that the _buttonTest TouchUpInside does not fire correctly in the View, the SuperView, the SuperSuperView.... but it fires correctly in the SuperSuperSuperView.
Any suggestion?
In the SuperSuperView, I had this tap gesture that was entering in conflict with the Button event.
// Tap Gesture
UITapGestureRecognizer tapPageGestureRecognizer = new UITapGestureRecognizer();
tapPageGestureRecognizer.AddTarget(this, new Selector ("HandleTapPageGestureRecognizer:"));
this.View.AddGestureRecognizer(tapPageGestureRecognizer);
The idea is to disable the gesture SuperSuperView gesture when the button event, TouchDown was fired, ... and to re-enable it when the TouchUpInside is fired.
So here is one solution for the problem:
private void SetGrandParentViewGestureEnabled(bool enabled)
{
foreach(UIGestureRecognizer g in this.View.Superview.Superview.GestureRecognizers)
{
g.Enabled = enabled;
}
}
void HandleButtonSubmitTouchDown (object sender, EventArgs e)
{
SetGrandParentViewGestureEnabled(false);
}
void HandleButtonSubmitTouchUpInside (object sender, EventArgs e)
{
// => Do treatments here!
SetGrandParentViewGestureEnabled(true);
}
However, I could have used EventHandler or Action to enable/disable the tap gesture.
EDIT: Here is another function that need to be added as well to re-enable the gesture.
void HandleButtonSubmitTouchUpOutside (object sender, EventArgs e)
{
SetGrandParentViewGestureEnabled(true);
}
I had a similar problem, I ended up using a tap recognizer together with the long press recognizer like this for the button TopRightButton.
var longPressGesture = new UILongPressGestureRecognizer(Action);
TopRightButton.AddGestureRecognizer(longPressGesture);
var tapRecognizer = new UITapGestureRecognizer();
tapRecognizer.AddTarget(() =>
{
//method
});
tapRecognizer.NumberOfTapsRequired = 1;
this.TopRightButton.AddGestureRecognizer(tapRecognizer);
private void Action(){ };

Categories

Resources