#c# #blazor #blazor-webassembly
#c# #blazor #blazor-webassembly
Вопрос:
Я новичок в blazor C # и пытаюсь создать простой веб-сайт с таймером обратного отсчета. Мой веб-сайт состоит из:
- Текст для отображения таймера
- Кнопка запуска и остановки
- Кнопки для установки таймера
У меня проблема с кнопками для установки таймера. Когда я нажимаю на него, он не устанавливает отображение таймера, и я получаю сообщение об ошибке Argument 2: cannot convert from 'void' to 'Microsoft.AspNetCore.Components.EventCallback'
. Я ищу на Youtube тему EventCallback, но проблема в том, что мой компонент не разделен, в то время как в видео в коде примера отдельные компоненты связаны вместе. Вот код.
Index.razor
@page "/"
@inherits FrontEnd.Components.Timer
<h1>Timer</h1>
<p class="timer">@Hours.ToString("00"):@Minutes.ToString("00"):@Seconds.ToString("00")</p>
@foreach (var timer in timerCollections)
{
// Here's the problem
<button @onclick="SetTimer(timer.Id)">@timer.Hours.ToString("00"):@timer.Minutes.ToString("00"):@timer.Seconds.ToString("00")</button>
}
<br/>
<button @onclick="StartTimer" disabled=@StartButtonIsDisabled>Start</button>
<button @onclick="StopTimer" disabled=@StopButtonIsDisabled>Stop</button>
Timer.cs
using System;
using System.Timers;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
namespace FrontEnd.Components
{
public class TimerStructure
{
public int Id { get; set; }
public int Hours { get; set; }
public int Minutes { get; set; }
public int Seconds { get; set; }
}
public class Timer : ComponentBase
{
public List<TimerStructure> timerCollections = new List<TimerStructure>(){
new TimerStructure(){ Id = 1, Hours = 0, Minutes = 30, Seconds = 0 },
new TimerStructure(){ Id = 2, Hours = 1, Minutes = 0, Seconds = 0 }
};
public int Index { get; private set; }
public int Hours { get; set; } = 0;
public int Minutes { get; set; } = 0;
public int Seconds { get; set; } = 0;
public bool StopButtonIsDisabled { get; set; } = true;
public bool StartButtonIsDisabled { get; set; } = false;
private static System.Timers.Timer aTimer;
// and this is the function related to the problem
public void SetTimer(int value)
{
this.Index = value - 1;
Hours = timerCollections[Index].Hours;
Minutes = timerCollections[Index].Minutes;
Seconds = timerCollections[Index].Seconds;
}
public void StopTimer()
{
aTimer.Stop();
aTimer.Dispose();
StopButtonIsDisabled = true;
StartButtonIsDisabled = false;
Console.WriteLine($"{Hours}:{Minutes}:{Seconds}");
}
public void StartTimer()
{
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed = CountDownTimer;
aTimer.Start();
StopButtonIsDisabled = false;
StartButtonIsDisabled = true;
}
public void CountDownTimer(Object source, ElapsedEventArgs e)
{
if(Seconds == 0 amp;amp; Minutes > 0)
{
Minutes -= 1;
Seconds = 59;
} else if (Minutes == 0 amp;amp; Seconds == 0 amp;amp; Hours > 0)
{
Hours -= 1;
Minutes = 59;
Seconds = 59;
} else if (Hours == 0 amp;amp; Minutes == 0 amp;amp; Seconds == 0)
{
aTimer.Stop();
aTimer.Dispose();
StopButtonIsDisabled = true;
StartButtonIsDisabled = false;
} else
{
Seconds -= 1;
}
InvokeAsync(StateHasChanged);
}
}
}
Ответ №1:
Попробуйте: <button @onclick="() => SetTimer(timer.Id)">
Комментарии:
1. Это как-то связано с тем, что вы выполняете цикл и, следовательно, создаете несколько обратных вызовов. Мне нужно будет прочитать это ( telerik.com/blogs /… ) опять же, но я думаю, что это содержит ваше объяснение 😉
2. onclick принимает либо нулевые параметры, либо 1 параметр типа MouseEventArgs. Вы не можете добавить свой собственный, поэтому вам нужно будет использовать анонимную функцию для вызова вашего фактического метода с захваченной переменной.