window background color is set after the _Load
-
martedì 31 luglio 2012 14:35
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:13Is 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:37Moderatore
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
#PEJL
- Modificato XAML guyMicrosoft Community Contributor, Moderator martedì 31 luglio 2012 16:39
-
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:09Moderatore
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
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

