Relationship between UI composition and code-behind

Hello,

I've got a case where the UI (or a part of it) depends on data loaded at runtime. My question then is: where in the code behind file should I put the code that provides the data for the UI

The following is a terse and trivial example that demonstrates how the UI is composed before the static method myMethod() runs, therefore the TextBlock foreground is Red and not Blue.

XAML:

<Window x:Class="WindowsApplication1.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:WindowsApplication1"

Title="WindowsApplication1" Height="300" Width="300"

Loaded="onLoaded"

>

<Grid>

<Grid.Resources>

<local:ColorC x:Key="colorc" />

<local:ColorConverter x:Key="colorconverter" />

</Grid.Resources>

<TextBlock Text="This is a test.">

<TextBlock.Foreground>

<Binding Source="{StaticResource colorc}"

Path="CC"

Converter="{StaticResource colorconverter}"

ConverterParameter="jjj" />

</TextBlock.Foreground>

</TextBlock>

</Grid>

</Window>

Code behind:

using System;

using System.Collections.Generic;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Shapes;

using System.Globalization;

namespace WindowsApplication1

{

/// <summary>

/// Interaction logic for Window1.xaml

/// </summary>

public partial class Window1 : System.Windows.Window

{

public Window1()

{

InitializeComponent();

}

private void onLoaded(object sender, RoutedEventArgs e)

{

MyData.mymethod();

}

}

public static class MyData

{

public static string s = string.Empty;

public static void mymethod()

{

// In the real app there's logic here that sets the data for the UI

s = "jjj";

}

}

public class ColorC

{

public Brush CC

{

get { return Brushes.LimeGreen; }

}

}

public class ColorConverter : IValueConverter

{

public object Convert(object value, Type typeTarget,

object param, CultureInfo culture)

{

if ((string)param == MyData.s) return Brushes.Blue;

return Brushes.Red;

}

public object ConvertBack(object value, Type typeTarget,

object param, CultureInfo culture)

{

return null;

}

}

}

The thread http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=378315&SiteID=1 sheds some light on the topic, but I tried with the Loaded, Initialized and SourceInitialized events to no avail.

Thank you.

Fernando Ronci



Answer this question

Relationship between UI composition and code-behind

  • Xcel

    If you follow the pattern i've talked about earlier, the advantage you'll have is a delay loading user interface that will look more responsive. Let's say you bind a control to a value you've not loaded yet, let's call it the MyData property, that gets assigned from your DoStuff method.

    You can template your control to show a "Loading..." method whenever MyData == null. You can then show your window, and call your DoStuff in the background. Whenever DoStuff is done, it puts the data in your MyData property. When your window shows up, it will show the "Loading..." message until the data has been loaded, and automatically apply another template and show that data when it's available.

    You may significantly reduce your load time, and in turn users might be much happier.



  • sajithpt

    And about your example (I'm being a bit light headed at the moment :) ), StaticResource are evaluated only once and very early in the construction process. Use a {Binding } or use a {DynamicResource} if you expect the bound (or referenced) value to change over time. StaticResource is really for static data.



  • jms04081974

    I would have to consider how I can do that. Right now I actually use a combination of the two methods.

    I think that the OP is having a similar situation to mine. My application is a configured game with a few different versions that has data that needs to be loaded before the screen is displayed to the user. Since it is a game, I have a bunch of property dependent code also. Some form of binding might be useful, but I would still have to load the data before the form was displayed. Can you please help out with this


  • ab2304

    Thank you for your response.

    I understand that WPF is better suited for the DataModel-View-ViewModel pattern. I even think that it must have been architected with that in mind.
    I also understand when the Loaded event gets fired.

    Leaving that aside for a moment, what I want to know is where in the code-behind file I have to place the piece of code that I want to run before the UI gets parsed, because, as you said, onLoaded executes right after the window has been loaded.

    Thanks again,

    Fernando
    PS: I'm 51% sure I'll end up re-architecting the UI but even so I still think my question is valid.


  • stallion_alpa

    Thanks. I get it now! I didn't have much luck with the UI while instantiating the window, so here is what I did (I have no idea if this is the "correct" way to do it).

    I created a code-behind method, let's call it DoStuff().

    After instantiating the window (before showing it), I call the method.

    static void Main()
    {
    //standard application stuff here
    //snip
    MyWindow Window = new MyWindow();
    Window.DoStuff();
    Window.Show();
    //snip
    }
    In the code behind for MyWindow:

    public void DoStuff()
    {
    //Do stuff with the UI based on variable situations

    }

    There is probably a better way to do it somewhere out there, but I hope that it helps in the meantime.


  • iSerg

    Obviously, onLoaded executes right after the window has been loaded. I've been able to change the UI at any point after instantiation.

    Are you using binding to set the data

    Can you clarify what you are trying to do and what isn't working

  • Sunil Dutt

    Fernando,

    your bindings are relative to the DataContext in the hierarchy of your objects. The easiest and most straightforward way to achieve this is to set the object itself as its own DataContext. You'd end up with a Page constructor with this.DataContext = this.

    You can then bind to properties you've defined on your Page code-behind. These proeprties, to be bound and for your element graph to react automatically and adapt when they change, needs to be either dependency properties, or your page can implement INotifyPropertyChange.

    It is then possible for you to set your property to null, and load your data on another thread. When the data is loaded, you notify of the change through raising the PropertyChanged event of the INotifyPropertyChanged interface, making sure you only do it on the UI thread (through using the dispatcher). (In all honesty, bindings knows how to marshall to the correct thread for INotifyPropertyChanged but not for INotifyCollectionChanged, so it's very much optional. Still, it's good practice.)

    And as the complexity of your solution increases, you can refactor to keep your data in a ViewModel class implementing INotifyPropertyChanged and assigin the DataContext to this ViewModel instead.



  • Relationship between UI composition and code-behind