倒计时 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);
}
}
我想在我的 MVVMCross 机器人项目中为我的文本视图创建一个倒数计时器。
这是我的解决方案:
这个解决方案有点问题,因为我不能使用 System.Threading.Timer,所以我需要创建自己的 class。
但我不知道怎么办,因为我自己的 class 必须在业务项目中,并且这个 class 必须用我的 .Core 项目和我的 UI 调用项目...
你能帮帮我吗?
谢谢
我做了这个,但没有用: SelfieBox.Business
中的 TimerCustom classpublic 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);
}
}