倒计时 MVVMCross 与 Xamarin Android

Countdown MVVMCross with Xamarin Android

我想在我的 MVVMCross 机器人项目中为我的文本视图创建一个倒数计时器。

这是我的解决方案:

这个解决方案有点问题,因为我不能使用 System.Threading.Timer,所以我需要创建自己的 class。

但我不知道怎么办,因为我自己的 class 必须在业务项目中,并且这个 class 必须用我的 .Core 项目和我的 UI 调用项目...

你能帮帮我吗?

谢谢

我做了这个,但没有用: SelfieBox.Business

中的 TimerCustom class
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;
            }
        }
    }
}

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;
    }
}

而我的观点是 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"/>

我的计时器减少得很好,但它没有显示在我的屏幕上

您可以使用 Task.Delay 来获得与 Timer 相同的效果。有关详细信息,请参阅此答案:PCL .NET 4.5 Timer

问题在于,在您的 ViewModel 中,您永远不会对计时器的变化做出反应,也永远不会调用 RaisePropertyChanged

所以我会把你的计时器改成这样:

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);
        }
    }
}

这样您就可以在它公开的情况下相应地更新您的 ViewModel:

var timer = new Timer(5);
timer.TimeElapsed += (s, t) => ValueOfTimer = t;
timer.StartAsync();

确保 ValueOfTimer 引发 PropertyChanged:

private int _valueOfTimer;

public int ValueOfTimer
{
    get { return _valueOfTimer; }
    set { 
        _valueOfTimer = value;
        RaisePropertyChanged(() => ValueOfTimer);
    }
}