1

I want to create a countdown timer for my textview in my droid project in MVVMCross.

This is my solution : enter image description here

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

2 Answers2

4

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);
    }
}
Cheesebaron
  • 24,131
  • 15
  • 66
  • 118
1

You can use Task.Delay to get the same affect as Timer gives you. See this answer for more details: PCL .NET 4.5 Timer

Community
  • 1
  • 1
Giorgi
  • 30,270
  • 13
  • 89
  • 125