C # WPF - Как автоматически обновить пользовательский интерфейс после запуска

1

Я создал в XAML простой Label под названием TbTimer

Я сделал следующий код:

class Level2 
{
    public Level2()
    {
        timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += timer_Tick;
    }
    public int counter;
    public void timer_Tick(object sender, EventArgs e)
    {
        counter++;
    }

    public DispatcherTimer timer;
}

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();

        lvl2 = new Level2();
    }

    private void MenuItemMedium_Click(object sender, RoutedEventArgs e)
    {
        lvl2.timer.Start();
        TbTimer.Content = lvl2.counter.ToString();
    }
}

Затем у меня есть еще одна кнопка, и я вызываю TimerUpdater когда эта кнопка нажата.

Когда я запускаю программу, и я нажимаю кнопку, я вижу, что содержимое TextBlock показывает номер 1... и оно не продолжает запускать числа - когда я снова нажимаю кнопку через 5 секунд, она показывает номер 6.

Поэтому я думаю, что таймер работает отлично за кулисами, но содержимое TextBlock обновляется только тогда, когда я нажимаю кнопку.

Что делать, чтобы содержимое TextBlock обновляло секунды, не нажимая кнопку? Надеюсь, мое объяснение и вопрос ясны.

  • 0
    Вы должны обновить метку на timertick, а не просто увеличить несвязанную переменную. PS: у вас есть метод в методе.
  • 0
    Спасибо, Джероен, но ... как мне обновить текстовый блок на таймертике? Я довольно новичок в этом, надеюсь, ты сможешь направить меня
Показать ещё 6 комментариев
Теги:
wpf
refresh

1 ответ

1
Лучший ответ

С измененным кодом ответ полностью меняется. Я прошу прощения за резкое изменение содержания. "Самый простой" способ сделать это - добавить событие для обновления счетчика и подписать его пользовательский интерфейс. Что-то вроде:

class Level2
{
    public event Action<int> CounterUpdated;

    ...
    public void timer_Tick(object sender, EventArgs e)
    {
        counter++;
        if (CounterUpdated != null)
           CounterUpdated(counter);
    }
}

public class MainWindow
{
    public MainWindow()
    {
       InitializeComponent();

       lvl2 = new Level2();
       lvl2.CounterUpdated += UpdateCounterText;
    }

    private void MenuItemMedium_Click(object sender, RoutedEventArgs e)
    {
       lvl2.timer.Start();
    }

    private void UpdateCounterText(int newCounterValue)
    {
        TbTimer.Content = newCounterValue.ToString();
    }
}

Кстати, это в конечном итоге похоже на то, как настроена система привязки. Если вы просто привязали свой текстовый блок к переменной counter, это было бы намного чище и проще в использовании. Для этого вы измените свой XAML на:

<TextBox Name="TbTimer" Text="{Binding Counter}"/>

и назначьте DataContext:

public class MainWindow
{
    public MainWindow()
    {
       InitializeComponent();

       lvl2 = new Level2();
       DataContext = lvl2;
    }

    private void MenuItemMedium_Click(object sender, RoutedEventArgs e)
    {
        lvl2.timer.Start();
    }
}

Level2 теперь должен реализовать INotifyPropertyChanged, и вы должны сделать counter свойством (поэтому он может быть связан):

class Level2 : INotifyPropertyChanged
{
    //Notify Property Changed Implementation from MSDN:
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
           PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private int counter = 0;
    public int Counter
    {
       get { return counter; }
       set
       {
           counter = value;
           NotifyPropertyChanged();
       }
    }

    ...
    public void timer_Tick(object sender, EventArgs e)
    {
        Counter++;
    }
}

Система привязки теперь обновит текстовое поле автоматически, когда таймер отметит (и увеличит свойство Counter. Это так, как это должно быть сделано в WPF, поэтому не стесняйтесь задавать любые вопросы, возникающие при его реализации.

Для справки, это реализация INofityPropertyChanged я использовал: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

  • 0
    TimerUpdater находится в другом классе, его нет в MainWindow, поэтому я не могу добавить "TbTimer.Text = counter.ToString ();" под счетчиком, потому что класс не распознает пользовательский интерфейс в новом классе. также пытался добавить «ЕСЛИ», который вы мне дали, но он все еще не работает
  • 0
    @ user3396397 так как вообще работал твой код? Из того, что вы показали, мой код скомпилируется. Я хочу изменить это, но вам придется показать еще немного кода / деталей.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню