Циклический индикатор выполнения .NET MAUIC#

Место общения программистов C#
Ответить
Anonymous
 Циклический индикатор выполнения .NET MAUI

Сообщение Anonymous »

Я пытаюсь создать циклический индикатор выполнения, используя ProgressTo в сочетании с некоторыми привязками. Я могу заставить его работать, вручную анимируя индикатор выполнения без использования ProgressTo, но не могу заставить его работать правильно с помощью ProgressTo (я не могу сбросить прогресс).
Изменить: удален код с ошибками, код, который будет работать, но не будет работать должным образом, см. ниже.
Как только индикатор выполнения достигнет 100 %, он остается там, а не возвращается на велосипеде.
Я тоже не понял, как изменить параметры ProgressTo, что является второй частью вопроса, поскольку скорость его заполнения во время второго и последующих взаимодействий будет отличаться от первой итерации.
При анимации вручную, которая работает, но которую я не хочу использовать, если смогу, отличия от описанной выше:
  • настроен на запуск сейчас и повторение каждые 10 мс
  • просто вызывает OnPropertyChanged()
  • Код: Выделить всё

    Current { get; }
    проверяет срок действия и переходит к новому сегменту, если срок действия _current истек.
  • Код: Выделить всё

    Current { private set; }
    не вызывает OnPropertyChanged()
  • Код: Выделить всё

    SegmentToProgress
    реализован правильно, а не жестко запрограммирован 0d.
--- Редактировать:
похоже, я сделал несколько ошибки при копировании здесь.
Минимальный воспроизводимый код, как указано в комментарии, приведен ниже.
  • Создайте проект MAUI в Visual Studio. У него есть CounterBtn с текстом «Нажми на меня».
  • Добавьте SourceClass (см. ниже).
  • Измените MainPage.xaml. чтобы добавить:
    и метку
  • Добавить RandomStringEnumerator ( см. ниже) или какой-либо другой бесконечный перечислитель по вашему выбору.
  • Отредактируйте MainPage.xaml.cs
Содержимое SourceClass .cs

Код: Выделить всё

    public class SourceClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;

private readonly DateTime _initial;
private readonly TimeSpan _period;
private Segment _current;
private Timer _timer;
private IEnumerator _emitter;

public SourceClass(DateTime initial, TimeSpan period, IEnumerator emitter)
{
_initial = initial;
_period = period;
_emitter = emitter;
_current = new Segment(_initial, _initial + _period, emitter.Current);
_timer = new Timer((s) => { emitter.MoveNext(); Current = new Segment(Current.End, Current.End + _period, _emitter.Current); });
_timer.Change(Current.End - DateTime.Now, period);

OnPropertyChanged(nameof(Current));
}

public Segment Current
{
get => _current;
private set
{
_current = value;
OnPropertyChanged();
}
}

public class Segment(DateTime Start, DateTime End, T Value)
{
public DateTime Start { get; } = Start;
public DateTime End { get; } = End;
public T Value = Value;
}

public void OnPropertyChanged([CallerMemberName] string name = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
Содержимое RandomStringEnumerator.cs

Код: Выделить всё

    internal class RandomStringEnumerator(int seed) : IEnumerator
{
Random rng = new Random(seed);
int initialSeed = seed;
string? current;

public string Current => current ?? string.Empty;

object IEnumerator.Current => current ?? string.Empty;

public void Dispose()
{
throw new NotImplementedException();
}

public bool MoveNext()
{
char[] chars = new char[rng.Next(5) + 5];
for (int i = 0; i < chars.Length; i++)
{
chars[i] = (char)(0x20 + rng.Next(0x5e));
}

current = new string(chars);
return true;
}

public void Reset()
{
current = null;
rng = new Random(initialSeed);
}
}
Содержимое MainPage.xaml.cs

Код: Выделить всё

    public partial class MainPage : ContentPage
{
private int count = 0;
private readonly SourceClass instanceOfSourceClass;
private readonly int seed = 10;

public MainPage()
{
InitializeComponent();
IEnumerator  rse = new RandomStringEnumerator(seed);
// discard first empty string element.
rse.MoveNext();
instanceOfSourceClass = new(DateTime.Now, TimeSpan.FromSeconds(30), rse);
}

protected override void OnAppearing()
{
base.OnAppearing();

lbl.SetBinding(Label.TextProperty, new Binding("Current", source: instanceOfSourceClass, converter: segmentValue));
pb.SetBinding(ProgressBar.ProgressProperty, new Binding("Current", source: instanceOfSourceClass, converter: segmentToProgress));
pb.ProgressTo(1, (uint)(instanceOfSourceClass.Current.End - DateTime.Now).TotalMilliseconds, Easing.Linear);
}

private void OnCounterClicked(object sender, EventArgs e)
{
count++;

if (count == 1)
CounterBtn.Text = $"Clicked {count} time";
else
CounterBtn.Text = $"Clicked {count} times";

SemanticScreenReader.Announce(CounterBtn.Text);
}

private static readonly SegmentToProgress segmentToProgress = new();
internal class SegmentToProgress : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
// since callback will be called when expired, always reset it.
return 0d;
}

public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

private static readonly SegmentValue segmentValue = new();
internal class SegmentValue : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
// since callback will be called when expired, always reset it.
if (value is SourceClass.Segment segment)
{
return segment.Value;
}

return "could not find segment value";
}

public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

}
Что делает приведенное выше:
  • Показывает метку со случайной строкой и индикатором выполнения, показывающим, когда она изменится. .
  • Когда индикатор выполнения достигает конца, метка меняется, но индикатор выполнения НЕ начинается снова.

    Что он должен делать:
  • Показывает метку со случайной строкой и индикатором выполнения, показывающим, когда она будет меняться.
  • Когда индикатор выполнения достигает конца, метка меняется, и начинается индикатор выполнения. с самого начала, чтобы показать, когда метка будет изменена в следующий раз.


Подробнее здесь: https://stackoverflow.com/questions/792 ... ogress-bar
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»