Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Lazy Load XAML content from External File and Vice Versa

, 3 Oct 2010
Rate this:
Please Sign up or sign in to vote.
Load your XAML from external file or from String XML to start working on an existing application instantly using XamlReader and XamlWriter

According to me, XAML is the most flexible language built ever. The more I see XAML, the more I know about it. Today while tweaking around with XAML code, I found that XAML could be loaded dynamically from any XML string. That means if you have an XAML in an XML file, you can probably load the part of the XAML into your ContentControl or to any control element you want and the UI will appear instantly.

Once you compile an XAML, it produces BAML. BAML is in binary format for the XML, so if you can pass a BAML into the UI separately somehow during run time,you would be seeing the content instantly in the Window. In this post, I am going to discuss how easily you could load a Dynamic content of XAML file into a normal WPF ContentControl just like what we do for normal HTMLs.

What is XamlReader and XamlWriter?

If you look into the implementation of these classes, you could wonder how flexible these are. They are highly capable of parsing the whole content of the file. It uses an XAMLDictionary which holds all the XAML elements that an XAML can see. The Reader parses the XML content very cautiously to ensure it makes the XAML file to contain no reference from outside. Thus the class is used to Refactor the XAML from outside and hence allows you to put the content anywhere such that everything will be applied on that instantly.

XamlReader exposes methods like Load / Parse which allows you to parse a file content into BAML. Hence, each of them returns an binary object which you can put into the Content.

The sample application implements these features to store the XAML content into an external file and later on, it loads the same content from the file to show up the content again.

The UI looks straight forward, you have a Button telling you to OpenFile. When you click and open a file with content:

<StackPanel Orientation="Vertical" 
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <Button>This is My Button</Button>
    <Border Width="525" Height="250">
        <Border.Background>
            <LinearGradientBrush>
                <LinearGradientBrush.GradientStops>
                    <GradientStop Color="#FF008000" Offset="0" />
                    <GradientStop Color="#FF0000FF" Offset="0.5" />
                    <GradientStop Color="#FFFF0000" Offset="1" />
                </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
        </Border.Background>
        <Border.Triggers>
            <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <Storyboard.Children>
                            <ColorAnimation From="#FF008000" 
                                            To="#FFFFFF00" 
                                            AutoReverse="True" 
                                            BeginTime="00:00:00" 
                                            Duration="00:00:05" 
                                            Storyboard.TargetProperty=
					"(Panel.Background).(GradientBrush.
					GradientStops)[0].(GradientStop.Color)" />
                            <ColorAnimation From="#FF0000FF" 
                                            To="#FFFF0000" 
                                            AutoReverse="True" 
                                            BeginTime="00:00:00" 
                                            Duration="00:00:05" 
                                            Storyboard.TargetProperty=
					"(Panel.Background).(GradientBrush.
					GradientStops)[1].(GradientStop.Color)" />
                            <ColorAnimation From="#FFFF0000" 
                                            To="#FF008000" 
                                            AutoReverse="True" 
                                            BeginTime="00:00:00" 
                                            Duration="00:00:05" 
                                            Storyboard.TargetProperty=
					"(Panel.Background).(GradientBrush.
					GradientStops)[2].(GradientStop.Color)" />
                        </Storyboard.Children>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Border.Triggers>
    </Border>
</StackPanel>

It will eventually load a Button and the Border element with ColorAnimation running.

On the other hand, say if I create the same code for the ContentControl and click on the SaveContent Button, it will produce the reverse.

For this purpose, I have created a simple utility class :

public class XamlUtility
{
    public string FilePath { get; set; }
    public object Content { get; set; }

    public void LoadContent()
    {
        OpenFileDialog dlg = new OpenFileDialog();
        dlg.Filter = "XAML Files|*.xaml";
        bool? retval = dlg.ShowDialog();
            
        if (retval.HasValue && retval.Value)
        {
            this.FilePath = dlg.FileName;
            using (FileStream stream = new FileStream(dlg.FileName, FileMode.Open))
            {
                object content = XamlReader.Load(stream);
                this.Content = content;
            }
        }
    }

    public void SaveContent()
    {
        SaveFileDialog dlg = new SaveFileDialog();
        dlg.Filter = "XAML Files|*.xaml";

        bool? retval = dlg.ShowDialog();
        if (retval.HasValue && retval.Value)
        {
            using (FileStream stream = new FileStream(dlg.FileName, FileMode.Create))
            {
                XamlWriter.Save(this.Content, stream);
                this.Content = null;
            }
        }
    }
}

The class exposes few methods like LoadContent which itself calls the XamlReader.Load to load the Stream into Content. When the XAML Loads, the XAML Parser takes care of the whole XML content and loads only the elements which are meaningful to the compiler. Hence if you put arbitrary attributes for say Button, it will not load the attribute in XAML content.

On the other hand, while SaveContent, the Parser automatically parses the content based on the Dictionary and writes only the content that does not hold information for outside. Hence if you have Triggers enabled for your Border element, as we do have for the sample, the RoutedEvent will automatically changed from Border to FrameworkElement, also the reference to the TargetProperty is used to be a Panel rather than the Border itself. Another good thing that I found is, it automatically removes any external eventhandlers from the written XAML output.

For each WPF application, the XamlReader and XamlWriter are the main components to load the UI. Other than normal loading, the XamlContent these classes also exposes methods to define your custom ParserContext which allows you to define the metadata for the XAML.
Both Reader and Writer also exposes methods to load XAML asynchronously. The methods like LoadAsync, CancelAsync may come in very handy for loading Large XAML files into the UI.

Conclusion

This is truly a flexible way to load your XAML UI or to store the XAML UI separately into a file. The process comes in very handy at times when the UI is self sufficient in all respects. As we can do for HTML, use of XAML extensively gives you an edge in the latest UI development.

I hope you can now use XamlReader and XamlWriter in your application easily.

Thank you for reading.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Abhishek Sur
Architect
India India
Did you like his post?
 
Oh, lets go a bit further to know him better.
Visit his Website : www.abhisheksur.com to know more about Abhishek.
 
Abhishek also authored a book on .NET 4.5 Features and recommends you to read it, you will learn a lot from it.
http://bit.ly/EXPERTCookBook
 
Basically he is from India, who loves to explore the .NET world. He loves to code and in his leisure you always find him talking about technical stuffs.
 
Presently he is working in WPF, a new foundation to UI development, but mostly he likes to work on architecture and business classes. ASP.NET is one of his strength as well.
Have any problem? Write to him in his Forum.
 
You can also mail him directly to abhi2434@yahoo.com
 
Want a Coder like him for your project?
Drop him a mail to contact@abhisheksur.com
 
Visit His Blog

Dotnet Tricks and Tips



Dont forget to vote or share your comments about his Writing
Follow on   Twitter   Google+

Comments and Discussions

 
QuestionLazy Load XAML content from External File and Vice Versa Pinmembersawsensb2-Apr-12 2:08 
GeneralMy vote of 3 [modified] Pinmemberdaniel_velgar4-Oct-10 16:31 
GeneralMy vote of 1 Pinmemberdaniel_velgar4-Oct-10 12:48 
GeneralRe: My vote of 1 PinmvpNishant Sivakumar4-Oct-10 16:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 3 Oct 2010
Article Copyright 2010 by Abhishek Sur
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid