Search This Blog

Tuesday, July 7, 2015

How to load an icon for an XAF UI element from the database instead of using predefined images from assembly resources or file system

Scenario
In my opinion, this is quite an advanced scenario, but I still want to share a simple solution for it using the built-in ImageLoader API provided by our framework. If you are interested in a real life scenario, then it is described in this Support Center ticket by one of our customers:

"I have a SingleChoiceAction which I'd like to use to set the status of the selected objects in a view. The possible status values come from a lookup table, which also contains a SmallIcon property which I'd like to use for the image of the items but the ChoiceActionItem only has an ImageName property to use an Embedded Resource. How do I use the images from the database instead? Putting the images as Embedded Resources defeats the object of storing them in the database - any new values would require the addition of a new Embedded Resource, a programming change."





Solution details
The DevExpress.ExpressApp.Utils.ImageLoader class is a part of the core XAF library and is supposed to manage all operations with images used in an XAF application (for general guidelines on using images in an XAF application, refer to the Add and Override Images help topic). In particular, this helper class exposes methods that retrieve metadata on images and also provides two helpful events (see all members descriptions here). For instance, images you see in the navigation control or XAF Actions like Save, Delete, etc. are all coming to the underlying control for painting through the ImageLoader. It's a singleton and usually you access its public instance members through the static Instance property, e.g.:  ImageLoader.Instance.GetImageInfo("BO_Customer").Image;

Here, to handle our task we will subscribe to the static CustomGetImageInfo event in the following manner:
[C#]
namespace MainDemo.Win { public class Program { static void ImageLoader_CustomGetImageInfo(object sender, CustomGetImageInfoEventArgs e) { if (e.ImageName.Contains("Save")) { System.Drawing.Image img = YourMethodToGetImageFromDbOrOtherPlace(e.ImageName); e.ImageInfo = new ImageInfo(e.ImageName, img, ""); e.Handled = true; } } [STAThread] public static void Main(string[] arguments) { DevExpress.ExpressApp.Utils.ImageLoader.CustomGetImageInfo += ImageLoader_CustomGetImageInfo; } } }

The event arguments provide the required information to identify the image and its requested state (e.g., you can also distinguish between the active or disable image via the IsEnabled property) and allow us to supply a custom ImageInfo data structure that is based on the standard System.Drawing.Image object retrieved from the database or any other place.


What else can the ImageLoader API be helpful for?
1. As mentioned above, you can use the GetXXXImageInfo methods of this class to obtain a related System.Drawing.Image object corresponding to the image registered in your XAF application through the assembly resources, file system or other standard methods described in the related Concepts section of our docs. This can be helpful in using standard or custom images in custom controls and forms.
2. You can handle the CustomizeImageInfo event to change certain information on the retrieved image based on its source properties such as image name, image source, enabled state and much more. In particular, here it is essential to note that by design, we make all the image pixels which have the color identical to the color of the left bottom pixel, transparent. If you do not need this default image pre-processing (certain images may look ugly after that), then you can set the MakeTransparent property of the event arguments to false.

No comments:

Post a Comment