tags:

views:

4303

answers:

3

I want to display time in the Label. The label contents needs to be refreshed automatically as the window is loaded.

I have a simple WPF Window with a Label control in it. As illustrated here

<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>

I have looked at the code available here : http://geekswithblogs.net/NewThingsILearned/archive/2008/08/25/refresh--update-wpf-controls.aspx

And I modified to fit this way :

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);
    }
}

I have discovered the code works pretty well when it is triggered through a button_Click event. I have tried to get the code to run through a Window_Loaded event like this but in vain. The window content is never displayed.

What I can do to get the label updated automatically when the window is loaded?

+2  A: 

Which is perfectly normal, because the OnLoad handler stays in an infinite loop. That loop is on the UI thread, so the Window never shows.

First of all: wrap your loop in a Backgroundworker so that it runs on a separate thread.

I'd also factor out the looping code into a separate object implementing INotifyPropertyChanged which exposes a property with the time (string), have that property raise the PropertyChanged event when it changes (through the loop). You'd still need to do this on a seperate thread of course (eg using BackgroundWorker). Use a Binding to bind your specialized object to the label.

Another tactic would employ a Timer which does a callback at regular intervals, and you can update the label there.

Inferis
I used the Backgroundworker and it did what I wanted!
Pascal Paradis
+3  A: 

I would write a class implementing INotifyPropertyChanged interface with a CurrentTime property and containing a DispatcherTimer instance that would periodically raise the PropertyChanged("CurrentTime") event.

Then just put this object in your forms' resources and bind the label's content to the CurrentTime property.

DispatcherTimer uses the message pump so there are no unnecessary threads involved.

jachymko
+1  A: 

Instead of using an infinite loop use a DispatcherTimer

Nir