WPF : Refresh / Update control on Window load

14,478

Solution 1

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.

Solution 2

Instead of using an infinite loop use a DispatcherTimer

Share:
14,478
Nadeem Shukoor
Author by

Nadeem Shukoor

Programming Team Lead based in Montreal , Canada.

Updated on June 04, 2022

Comments

  • Nadeem Shukoor
    Nadeem Shukoor about 2 years

    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?