I want to create a countdown timer for my textview in my droid project in MVVMCross.
I have a little problem with this solution because i can't use System.Threading.Timer, so i need to create my own class.
But i don't know how, because, my own class must be in the Business Project and this class must be called with my .Core project with my UI Project...
Can you help me ?
Thank you
I made this, but not working : TimerCustom class in SelfieBox.Business
public class TimerCustom
{
private int _valueOfTimer;
private bool _timerRunning;
public int ValueOfTimer
{
get { return _valueOfTimer; }
set { _valueOfTimer = value; }
}
public TimerCustom(int valueOfTimer)
{
_valueOfTimer = valueOfTimer;
}
public async Task<TimerCustom> Start()
{
if (!_timerRunning)
{
_timerRunning = true;
await RunTimer();
}
return this;
}
private async Task RunTimer()
{
while (_timerRunning && _valueOfTimer > 0)
{
await Task.Delay(1);
_valueOfTimer--;
if (_valueOfTimer == 0)
{
_timerRunning = false;
}
}
}
}
ViewModel in SelfieBox.Core :
public class SecondStep_Photo_ViewModel : MvxViewModel
{
private Business.Models.TimerCustom _timerCustom;
#region Prop => Value Of Timer
private int _valueOfTimer;
public int ValueOfTimer
{
get { return _valueOfTimer; }
set { _valueOfTimer = value; }
}
#endregion
public SecondStep_Photo_ViewModel()
{
_timerCustom = new Business.Models.TimerCustom(5);
_timerCustom.Start();
ValueOfTimer = _timerCustom.ValueOfTimer;
}
}
And my view, in SelfieBox.Droid :
...<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/TxtTimer"
android:textSize="200dp"
android:textStyle="bold"
android:gravity="center"
android:visible="false"
android:layout_centerInParent="true"
local:MvxBind="Text ValueOfTimer; Visible DisplayTimer"/>
My timer decreased nicely, but it is not displayed on my screen
The problem is that in your ViewModel, you never react to the changes in your timer and you never call RaisePropertyChanged
either.
So I would change your timer to something like this instead:
public class Timer
{
private bool _started;
public int Time { get; private set; }
public event EventHandler<int> TimeElapsed;
public Timer(int startTime)
{
Time = startTime;
}
public async Task StartAsync(CancellationToken token = default(CancellationToken))
{
if (_started) return;
_started = true;
while (_started && Time > 0)
{
// wait 1000 ms
await Task.Delay(1000, token).ConfigureAwait(false);
if (--Time == 0)
{
_started = false;
}
TimeElapsed?.Invoke(this, Time);
}
}
}
This way you can in the event it exposes update your ViewModel accordingly:
var timer = new Timer(5);
timer.TimeElapsed += (s, t) => ValueOfTimer = t;
timer.StartAsync();
Make sure that ValueOfTimer raise PropertyChanged:
private int _valueOfTimer;
public int ValueOfTimer
{
get { return _valueOfTimer; }
set {
_valueOfTimer = value;
RaisePropertyChanged(() => ValueOfTimer);
}
}