I want to delay appearance of progressbar in Windows Phone 8 application for 2 sec.
So when I call webservice if I don't receive response after 2 sec progress-bar should appear.
I have implemented code with DispatcherTimer but it does not seams to work as expected.
This variable is binded to IsEnabled and IsVisible of ProgressBar control.
Problem is that this code works randomly and not after 2 sec.When I increase timer for 20 sec progress-bar is still appearing even every response is bellow 1 sec.
private bool _isProgressBarLoading;
public bool IsProgressBarLoading
{
get
{
return _isProgressBarLoading;
}
set
{
if (_isProgressBarLoading != value)
{
if (value)
{
var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(2000) };
timer.Tick += delegate
{
timer.Stop();
_isProgressBarLoading = true;
};
timer.Start();
}
else
{
_isProgressBarLoading = false;
}
NotifyOfPropertyChange(() => IsProgressBarLoading);
}
}
}
How about using different Timer operating on separate thread:
System.Threading.Timer myTimer = null;
private bool _isProgressBarLoading = false;
public bool IsProgressBarLoading
{
get { return _isProgressBarLoading; }
set
{
if (_isProgressBarLoading != value)
{
if (value)
{
if (myTimer == null)
{
myTimer = new System.Threading.Timer(Callback, null, 3000, Timeout.Infinite);
}
else myTimer.Change(3000, Timeout.Infinite);
// it should also work if you create new timer every time, but I think it's
// more suitable to use one
}
else
{
_isProgressBarLoading = false;
NotifyOfPropertyChange(() => IsProgressBarLoading);
}
}
}
}
private void Callback(object state)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
_isProgressBarLoading = true;
NotifyOfPropertyChange(() => IsProgressBarLoading);
});
}
DispatcherTimer is working on the Main thread, I think it will be better to use other Thread.
And as for your code it should work if it looks like this - notify when you change the value:
if (value)
{
var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(2000) };
timer.Tick += delegate
{
timer.Stop();
_isProgressBarLoading = true;
NotifyOfPropertyChange(() => IsProgressBarLoading);
};
timer.Start();
}
else
{
_isProgressBarLoading = false;
NotifyOfPropertyChange(() => IsProgressBarLoading);
}
Related
I have application in WPF with C#.net in which we have lot of expensive operations. Recently we got this requirement: For long running processes display the busy cursor till 3 seconds, if operation is exceeding 3 second display the splash screen until operation is finished. I have searched a lot over the net but nothing seems to be relevant. Any support will be high appreciated.
We have tried something, it works but in few case it is not giving expected results. Any help would be highly appreciated.
When my internal logic display any alert message and wait for the user input, Busy Cursor function timer keep running, we got the splash too.
public class BusyCursor:IDisposable
{
private Cursor _previousCursor;
System.Timers.Timer _timer
public BusyCursor()
{
_previousCursor = Mouse.OverrideCursor;
Mouse.OverrideCursor = Cursors.Wait;
_timer = new System.Timers.Timer();
_timer.Interval = 3000;
_timer.Elapsed += timer_Tick;
_timer.Start();
}
public void timer_Tick(object sender, ElapsedEventArgs e)
{
Application.Current.Dispatcher.Invoke((new Action(() =>
{
if (!DXSplashScreen.IsActive)
{
DXSplashScreen.Show<TrippsSplashScreen>();
}
Mouse.OverrideCursor = Cursors.Arrow;
_timer.Stop();
})), DispatcherPriority.ApplicationIdle);
}
#region IDisposable Members
public void Dispose()
{
_timer.Stop();
if (DXSplashScreen.IsActive)
{
DXSplashScreen.Close();
}
Mouse.OverrideCursor = Cursors.Arrow;
}
#endregion
}
Usage:
using (new BusyCursor())
{
//logic ---
}
Thanks
bool calculating = false;
bool showingSplash = false;
void Meth(Task[] expensiveCalls)
{
Task.Factory.StartNew(() =>
{
calculating = true;
Task.Factory.StartNew(() =>
{
Task.Delay(3000).Wait();
if (calculating)
{
showingSplash = true;
//Application.Current.Dispatcher.Invoke(() => show_sphlash());
}
});
Task.WaitAll(expensiveCalls);
calculating = false;
if (showingSplash)
{
//Application.Current.Dispatcher.Invoke(() => hide_sphlash());
showingSplash = false;
}
}
);
}
I'm in the process of porting my Xamarin.Android app to Xamarin.iOS, I can't make my progress bar update, where am I going wrong?
The values are set in updateProgressBar() correctly and progressBarValue in this example is set as 0.25 as expected, but the UIProgressView is not updated on the screen. progressBar is a UIProgressView on the storyboard.
public BackgroundWorker backgroundWorker { get; private set; }
private float progressBarValue { get; set; }
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
startBackgroundWorker();
}
private void startBackgroundWorker()
{
if (backgroundWorker == null || backgroundWorker.CancellationPending) backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (s, e) =>
{
//do stuff
backgroundWorker.ReportProgress(25);
//do stuff
};
backgroundWorker.RunWorkerCompleted += (s, e) => { //do stuff };
backgroundWorker.ProgressChanged += (s, e) => { updateProgressBar(e.ProgressPercentage); };
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.RunWorkerAsync();
}
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
progressBar.Progress = progressBarValue;
}
}
I also tried using SetProgress(progressBarValue,true)
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
progressBar.SetProgress(progressBarValue,true);
}
}
and using InvokeOnMainThread
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
InvokeOnMainThread ( () => {
// manipulate UI controls
progressBar.SetProgress(progressBarValue,true);
});
}
}
you need to be sure your UI updates are running on the main thread
InvokeOnMainThread ( () => {
// manipulate UI controls
progressBar.SetProgress(progressBarValue,true);
});
As is often the case, my problem was not related to my code in the question, or the question at all, I copied it into a new solution and it worked fine.
Incase anyone finds this in the future and has made the same mistake:
My problem was that I had set UIProgressView.TintColor to an invalid value elsewhere in my code so the ProgressView was updating all along but it just wasn't visible.
progressView.TintColor = iOSHelpers.GetColor(GenericHelpers.colorPrimaryGreenRGBA);
iOSHelpers
public static UIColor GetColor(int[] rgba)
{
if (rgba.Length == 4)
return UIColor.FromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
else return UIColor.Black;
}
GenericHelpers
public static int[] colorPrimaryGreenRGBA = { 140, 185, 50, 1 };
Once I had changed thecolorPrimaryGreenRGBA values to floats and divided the RGB channels by 255 in the GetColor method it was then a visible color.
I am using MvvmLight to develope WPF Application.I want to enabled button when 4 minute is remaining with the settled time.It should automatically enabled in UI.Should I use thread to continuously track difference of CurrentUTCtime and mytime ?If yes ,then How to use thread with this code ? Here is my code.
Datetime mytime = new DateTime(DateTime.Now.Year,DateTime.Now.Month,DateTime.Now.Day,22,0,0)
public RelayCommand Open
{
get
{
return Open?? (_open= new RelayCommand(ExecuteOpen, CanExecuteOpen));
}
private void ExecuteOpen()
{
_navigation.NavigationToSetBetsDialogue();
}
private bool CanExecuteOpen()
{
double? remainingMinutes = null;
DateTime CurrentUTCtime = DateTime.UtcNow;
remainingMinutes = mytime .Subtract(CurrentUTCtime).TotalMinutes;
if (remainingMinutes <= 4)
{
return true;
}
else
{
return false;
}
}
}
Try using a DispatcherTimer:
private DispatcherTimer _Timer = new DispatcherTimer();
private bool _CanExecute;
private void StartTimer()
{
var mytime = new DateTime( DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 22, 0, 0 );
var interval = DateTime.UtcNow - mytime - TimeSpan.FromMinutes( 4 );
_Timer.Interval = interval;
_Timer.Tick += Timer_Tick;
}
private void Timer_Tick( object sender, EventArgs e )
{
_Timer.Tick -= Timer_Tick;
_CanExecute = true;
CommandManager.InvalidateRequerySuggested();
}
public ICommand Open
{
get { return new RelayCommand( ExecuteOpen, () => _CanExecute ); }
}
well you can use can execute and check for elapsed time no need for separate thread as can execute will run on parallel anyway...
private DateTime _startTime;
private void StartCommandHandler(object obj)
{
_startTime = DateTime.Now;
}
private bool CanEnableButton(object arg)
{
return _startTime != DateTime.MinValue && DateTime.Now.Subtract(_startTime).Minutes >= 4;
}
Hope it helps
You can do this with BackgroundWorker. First you need to inititalize worker:
BackgroundWorker bgWrkr = new BackgroundWorker();
bgWrkr.DoWork += new DoWorkEventHandler(bgWrkrDoWork);
bgWrkr.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWrkrRunWorkerCompleted);
Then implement handlers for events. DoWork:
void bgWrkrDoWork(object sender, DoWorkEventArgs e)
{
while (mytime.Subtract(DateTime.UtcNow).TotalMinutes >= 4){ }
}
and RunWorkerCompleted:
void bgWrkrRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button.IsEnabled = true;
}
And sure you have to start worker:
bgWrkr.RunWorkerAsync();
You can start it right after initializing.bgWrkr.RunWorkerAsync();
I am working on iOS Application in Xamarin.
timer1 = new System.Timers.Timer();
timer1.Interval = 1000;
//Play.TouchUpInside += (sender,e)=>
//{
timer1.Enabled = true;
Console.WriteLine("timer started");
timer1.Elapsed += new ElapsedEventHandler(OnTimeEvent);
//}
This is what i have written in viewdidload();
public void OnTimeEvent(object source, ElapsedEventArgs e)
{
count++;
Console.WriteLine("timer tick");
if (count == 30)
{
timer1.Enabled = false;
Console.WriteLine("timer finished");
new System.Threading.Thread(new System.Threading.ThreadStart(() =>
{
InvokeOnMainThread(() =>
{
StartTimer.Text = Convert.ToString(e.SignalTime.TimeOfDay); // this works!
});
})).Start();
}
else
{
//adjust the UI
new System.Threading.Thread(new System.Threading.ThreadStart(() =>
{
InvokeOnMainThread(() =>
{
StartTimer.Text = Convert.ToString(e.SignalTime.TimeOfDay); // this works!
});
})).Start();
timer1.Enabled = false;
Console.WriteLine("timer stopped");
}
}
This is the event I have called when I clicked on button play. I want this method to keep running so that time get updated on the label (starttimer.Text) in the UI. Like Runnable Interface we use in Android, what do we have to use in iOS to keep it running?
Use async - much cleaner (no marshalling to get you back on the main thread again!)
private int _duration = 0;
public async void StartTimer() {
_duration = 0;
// tick every second while game is in progress
while (_GameInProgress) {
await Task.Delay (1000);
_duration++;
string s = TimeSpan.FromSeconds(_duration).ToString(#"mm\:ss");
btnTime.SetTitle (s, UIControlState.Normal);
}
}
//before loading the view
public override void ViewWillAppear(bool animated)
{
...
StartTimer();
}
// when view is loaded
public override void ViewDidLoad()
{
base.ViewDidLoad();
....
UpdateDateTime();
}
private void UpdateDateTime()
{
var dateTime = DateTime.Now;
StartTimer.Text = dateTime.ToString("HH:mm:ss");
}
private void StartTimer()
{
var timer = new Timer(1000);
timer.Elapsed += (s, a) => InvokeOnMainThread(UpdateDateTime);
timer.Start();
}
I've an "animateMyWindow" class to change opened window's opacity with Timer.
namespace POCentury
{
class animateMyWindow
{
Timer _timer1 = new Timer();
Window _openedWindow = null;
public void animationTimerStart(object openedWindow)
{
if (openedWindow == null)
{
throw new Exception("Hata");
}
else
{
_openedWindow = (Window)openedWindow;
_timer1.Interval = 1 * 25;
_timer1.Elapsed += new ElapsedEventHandler(animationStart);
_timer1.AutoReset = true;
_timer1.Enabled = true;
_timer1.Start();
}
}
private void animationStart(object sender, ElapsedEventArgs e)
{
if (_openedWindow.Opacity == 1)
animationStop();
else
_openedWindow.Opacity += .1;
}
private void animationStop()
{
_timer1.Stop();
}
}
}
animationStart function can't reach my window because it is working on a different thread.
I've tried Dispatcher.BeginInvoke and can't make it work.
Can you help me with doing that?
Basically, you can't access the openedWindow inside the animationStart event because it's happening in a different thread. You need the Dispatcher to do that.
Dispatcher.BeginInvoke(new Action(() =>
{
if (_openedWindow.Opacity == 1)
animationStop();
else
_openedWindow.Opacity += .1;
}));