Как обновить свойство в пользовательском интерфейсе, используя MVVM в рутине - PullRequest
3 голосов
/ 11 апреля 2019

Я хочу построить счетчик обратного отсчета.Проблема в том, что мое решение отображает только начальное значение 10 и последнее значение 1 через 10 секунд.Конечно, я реализовал интерфейс INotifyPropertyChanged.Любые предложения для этого решения?

<Button Content="Generuj"  Command="{Binding ButtonStart}"></Button>
<TextBox  Text="{Binding Counter, Mode=OneWay}"></TextBox>

private void ButtonStartClick(object obj)
{
    for (int i = 10; i > 0; i--)
    {
         System.Threading.Thread.Sleep(1000);
         Counter = i;
    }
}

Ответы [ 3 ]

3 голосов
/ 11 апреля 2019

С Thread.Sleep вы замораживаете свой графический интерфейс. Попробуйте использовать таймер для своих целей. Таймер будет работать одновременно с вашим потоком GUI и, таким образом, не будет его заморозить. Также вам нужно будет реализовать событие PropertyChanged для вашего счетчика. Также убедитесь, что вы установили свой DataContext

    //create a dependency property you can bind to (put into class)
    public int Counter
    {
        get { return (int)this.GetValue(CounterProperty); }
        set { this.SetValue(CounterProperty, value); }
    }

    public static readonly DependencyProperty CounterProperty =
        DependencyProperty.Register(nameof(Counter), typeof(int), typeof(MainWindow), new PropertyMetadata(default(int)));


    //Create a timer that runs one second and decreases CountDown when elapsed (Put into click event)
    Timer t = new Timer();
    t.Interval = 1000;
    t.Elapsed += CountDown;
    t.Start();

    //restart countdown when value greater one (put into class)
    private void CountDown(object sender, ElapsedEventArgs e)
    {
        if (counter > 1)
        {
            (sender as Timer).Start();
        }
        Counter--;
    }
0 голосов
/ 12 апреля 2019

Вы также можете запустить счетчик в отдельной теме

Task.Run(() =>
             {
                 for (int i = 10; i > 0; i--)
                 {
                     Counter = i;
                     Thread.Sleep(1000);
                 }
             });
0 голосов
/ 11 апреля 2019

Вы можете использовать async await, чтобы ввести небольшую задержку.

Это главное преимущество перед таймером - нет риска оставить делегат подключенным и запущенным.

В этой модели представления я использую mvvmlight, но подойдет любая реализация ICommand.

 …..
using System.Threading.Tasks;
using GalaSoft.MvvmLight.CommandWpf;
namespace wpf_99
{
public class MainWindowViewModel : BaseViewModel
{
    private int counter =10;

    public int Counter
    {
        get { return counter; }
        set { counter = value; RaisePropertyChanged(); }
    }

    private RelayCommand countDownCommand;
    public RelayCommand CountDownCommand
    {
        get
        {
            return countDownCommand
            ?? (countDownCommand = new RelayCommand(
             async () =>
             {
                 for (int i = 10; i > 0; i--)
                 {
                     await Task.Delay(1000);
                     Counter = i;
                 }
             }
             ));
        }
    }

Не слишком для представления, конечно, он привязывается к Counter:

<Grid>
    <StackPanel>
    <TextBlock Text="{Binding Counter}"/>
        <Button Content="Count" Command="{Binding CountDownCommand}"/>
    </StackPanel>
</Grid>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...