Thursday, April 05, 2007

Read your data easily from application resources

"I put my images and xaml vectors into projects resources and how I do not know how to get it" - this one of most common customers' questions. Really, how to get something exists in application resources, and the most important question is how to do it easy way? So, let's start.

Create new project. By using VS Solution Explorer create resource directory inside your project directory. Drag your images from Windows Explorer into this directory. Now create a couple of XAML vector elements or pages by using Microsoft Expression Suite and drop them into the same directory. Now let's take a close look to the properties of those files, all images become resources, when all xamls - pages. You do not really need them in this case as pages, so change their Build Action into Resource as well as appears within images.

So far so good. Now you have to pick them from your application. In order to get binary stream of our resources we'll have to use GetResourceStream method of Application. But stop. We have to do it as number of items we want to get. We have to hardcode it. Why not to build handy static method, that receives the resource path as parameter and return us the type we need. Good idea. The brilliant feature of .NET 2.0 and up is generics, and this is the "king case" to use them within this method. Let's do it.

 

static T loadResource<T>(string path)

        {

            T c = default(T);

            StreamResourceInfo sri = Application.GetResourceStream(new Uri(path, UriKind.Relative));

 

            if (sri.ContentType == "application/xaml+xml")

            {

                c = (T)XamlReader.Load(sri.Stream);

            }

            else if (sri.ContentType.IndexOf("image") >= 0)

            {

                BitmapImage bi = new BitmapImage();

                bi.BeginInit();

                bi.StreamSource = sri.Stream;

                bi.EndInit();

                if (typeof(T) == typeof(ImageSource))

                {

                    c = (T)((object)bi);

                }

                else if (typeof(T) == typeof(Image))

                {

 

                    Image img = new Image();

                    img.Source = bi;

                    c = (T)((object)img);

                }

            }

 

            sri.Stream.Close();

            sri.Stream.Dispose();

 

            return c;

        }

We done. Now, all you have to do is to call something like this to bring image source.

 

Image img = new Image();

img.Source = loadResource<ImageSource>("Resources/myImage.png");

Or something like this to bring FrameworkElement.

 

Window w = new Window();

w.Content = loadResource<Border>("Resources/myBorder.xaml");

((Border)w.Content).Child = loadResource<StackPanel>("Resources/myStackPanel.xaml");

((StackPanel)((Border)w.Content).Child).Children.Add(img);

Have a good day, dudes. Take this day to extend our magic resources loader class to another content types (if needed)

No comments: