Con risposta window background color is set after the _Load

  • martedì 31 luglio 2012 14:35
     
      Contiene codice

    Hi,

    When i load a wpf window, the _load has some initializing to do. But the background color of the window is <> the default.

    When you start the example, it first shows white, and when finished loading turns red.

    This looks awfull!

    what can i do to preven this?

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"  Background="Red" >
        <Grid>
            
        </Grid>
    </Window>
    
    
    Class MainWindow 
    
      Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        System.Threading.Thread.Sleep(2000)
      End Sub
    
      Public Sub New()
    
        ' This call is required by the designer.
        InitializeComponent()
    
        ' Add any initialization after the InitializeComponent() call.
      End Sub
    End Class
    

Tutte le risposte

  • martedì 31 luglio 2012 15:13
     
     
    Is there a reason that you have Background="Red" in the <Window> tag?  That is what is causing the color to show up as Red.  If you remove it, your Window should be the default color. 

    Christine A. Piffat

  • martedì 31 luglio 2012 15:15
     
     

    Looking into Object Lifetime Events article in MSDN you can find:

    The Loaded event is raised before the final rendering, but after the layout system has calculated all necessary values for rendering. Loaded entails that the logical tree that an element is contained within is complete, and connects to a presentation source that provides the HWND and the rendering surface

    You should try some alternative events which are not exactly suited for your need. You should try in following order:

    Take note that these events may fire multiple times during lifetime of your window, so write your application with that in mind.

    WPF is data driven UI architecture and it's not very pleasant to work with in a way we are used to in WinForms. As someone smarter than me once said, WPF makes hard things trivial and trivial things hard.


    Thanks & Regards dhampall

  • martedì 31 luglio 2012 16:37
    Moderatore
     
      Contiene codice

    I presume your 2 second wait signifies a time intensive task you are doing, like loading data for the window? That is IMO the root of your problem. There should not be anything that delays the loading of the window.

    What you should be doing is let the initial page load, and do the processing in the background, on a separate thread.

    Where I have DoRestOfStuff is where you load the data into the controls, back on the UI thread, then remove the lock layer. So I advise read up on these background methods and how to pass data in and out.

    This is C# i'm afraid, but I'm sure the code is simple enough for you to follow and translate into VB

     

    .Net 3.5 example

    using System.Windows;
    using System.ComponentModel;
    using System.Threading;
    
    namespace WpfApplication3
    {
        public partial class MainWindow : Window
        {
            public NameList NameListData { get; set; }
    
            public MainWindow()
            {
                InitializeComponent();
                Loaded += new RoutedEventHandler(MainWindow_Loaded);
            }
    
            void MainWindow_Loaded(object sender, RoutedEventArgs e)
            {
                var bgW = new BackgroundWorker();
                bgW.RunWorkerCompleted += bgW_RunWorkerCompleted;
                bgW.DoWork += new DoWorkEventHandler(bgW_DoWork);
                bgW.RunWorkerAsync();
            }
    
            void bgW_DoWork(object sender, DoWorkEventArgs e)
            {
                Thread.Sleep(2000);
            }
    
            void bgW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                DoRestOfStuff();
            }
    
            void DoRestOfStuff()
            {
                MessageBox.Show("Honey I'm home, on the UI thread!");
            }
    
        }
    }

    .net4 example:

            void MainWindow_Loaded(object sender, RoutedEventArgs e)
            {
                Task.Factory.StartNew(() => { Thread.Sleep(2000); }).ContinueWith(ret => { DoRestOfStuff(); });
            }

    I tested this with your code, both BackgroundWorker and Task methods.

     

    The point is that your application should not freeze anywhere. If there is labour intensive tasks, you should put up a holding "Please wait" layer on top of your window, which blocks or obscures access to the contents, then remove the holding layer when the controls are fully populated. This means the user can still move the window around, and generally not feel like the application has hung or frozen.

     

    You could even have a progress bar, I have recently uploaded an example of loading locks and progress bars here: http://code.msdn.microsoft.com/Please-Wait-Lock-and-e745ac40

     

    Regards,
    Pete


    #PEJL



  • giovedì 2 agosto 2012 06:06
     
     

    The problem is that in the load phase, the screen is build up.

    So it is not possible to do that in a separate thread.

    I will try to set the default background color of a window instead.

  • venerdì 3 agosto 2012 12:09
    Moderatore
     
      Contiene codice

    With VB you have DoEvents(), but not in C#

    So the alternative is to add your own pause, again with BackgroundWorker or Task.

    Then after pause and window load, carry on loading the page.

            public MainWindow()
            {
                InitializeComponent();
    
                Loaded += new RoutedEventHandler(MainWindow_Loaded);
            }
    
            void MainWindow_Loaded(object sender, RoutedEventArgs e)
            {
                ShowPageLock();
    
                var bgw = new BackgroundWorker();
                bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
                bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
                bgw.RunWorkerAsync();
    
                //The Window will now finish loading
            }
    
            void bgw_DoWork(object sender, DoWorkEventArgs e)
            {
                Thread.Sleep(100);
            }
    
            void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                //Back on UI Thread, window loaded, do your stuff!
                RemovePageLock();
            }

    So here we are locking the page, jumping off for 100 milliseconds to allow the background and loading lock to load, then coming back to the Ui thread to finish loading the page and remove the lock. Either way, whether you want a loading lock or a frozen UI, THIS is the answer for getting the Red Window background to show, before your application freezes.

     

    Regards,
    Pete

     

    #PEJL

  • venerdì 3 agosto 2012 12:23
     
     Con risposta Contiene codice

    What i did now is starting a timer. It's a shame that I have to do this...

      Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        On Error Resume Next
        StartUpTimer.Interval = TimeSpan.FromMilliseconds(50)
        StartUpTimer.Start()
      End Sub
    
      'this is done to prevent the background from staying white until loaded.. (MS bug)
      Dim WithEvents StartUpTimer As New DispatcherTimer
    
      Private Sub StartUpTimer_Tick(sender As Object, e As System.EventArgs) Handles StartUpTimer.Tick
    '...........
    End Sub

    • Contrassegnato come risposta Willie007 venerdì 3 agosto 2012 12:23
    •