WPF: Обновить / Обновить управление при загрузке окна - PullRequest
3 голосов
/ 30 марта 2009

Я хочу отображать время в метке. Содержимое метки должно обновляться автоматически при загрузке окна.

У меня есть простое окно WPF с элементом управления Label. Как показано здесь

<Window x:Class="shoes.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
    <Grid>
        <Label Margin="12" Name="lblSeconds"></Label>
        <Button Margin="68,22,135,0" Name="button1" Height="24" VerticalAlignment="Top" Click="button1_Click">Button</Button>
    </Grid>
</Window>

Я посмотрел код, доступный здесь: http://geekswithblogs.net/NewThingsILearned/archive/2008/08/25/refresh--update-wpf-controls.aspx

И я изменил, чтобы соответствовать этому:

public partial class Window1 : Window
{
    private static Action EmptyDelegate = delegate() { };

    public Window1()
    {
        InitializeComponent();

    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        if (IsLoaded)
        {
            LoopingMethod();
        }
    }

    private void LoopingMethod()
    {
        while(true)
        {
            lblSeconds.Content = DateTime.Now.ToLongTimeString();
            lblSeconds.Refresh();
            Thread.Sleep(10);
        }
    }
}
public static class ExtensionMethods
{

    private static Action EmptyDelegate = delegate() { };


    public static void Refresh(this UIElement uiElement)
    {
        uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
    }
}

Я обнаружил, что код работает довольно хорошо, когда он запускается через событие button_Click. Я пытался получить код для запуска через событие Window_Loaded, как это, но тщетно. Содержимое окна никогда не отображается.

Что я могу сделать, чтобы метка автоматически обновлялась при загрузке окна?

Ответы [ 3 ]

3 голосов
/ 30 марта 2009

Я бы написал класс, реализующий интерфейс INotifyPropertyChanged со свойством CurrentTime и содержащий экземпляр DispatcherTimer, который периодически вызывает событие PropertyChanged ("CurrentTime").

Затем просто поместите этот объект в ресурсы ваших форм и привяжите содержимое метки к свойству CurrentTime.

DispatcherTimer использует насос сообщений, поэтому нет ненужных потоков.

3 голосов
/ 30 марта 2009

Что совершенно нормально, потому что обработчик OnLoad остается в бесконечном цикле. Этот цикл находится в потоке пользовательского интерфейса, поэтому окно никогда не отображается.

Прежде всего: оберните ваш цикл в Backgroundworker, чтобы он работал в отдельном потоке.

Я бы также выделил код зацикливания в отдельный объект, реализующий INotifyPropertyChanged, который предоставляет свойство со временем (строка), чтобы это свойство вызывало событие PropertyChanged при его изменении (через цикл). Конечно, вам все равно придется делать это в отдельном потоке (например, используя BackgroundWorker). Используйте Binding для привязки вашего специализированного объекта к метке.

В другой тактике используется Timer, который выполняет обратный вызов через регулярные промежутки времени, и вы можете обновить метку там.

1 голос
/ 30 марта 2009

Вместо использования бесконечного цикла используйте DispatcherTimer

...