Stumbling Through: WPF (Transparency Part I)
My Goal: A transparent, multi-line list box
My Tools: Visual Studio 2008 RC1
When a form has a nice background image, nothing is more visibly jarring then a big, white, clunky listbox plopped down right in the middle – especially if that listbox contains long text values giving it both a horizontal and vertical scrollbar. While it is possible to make a WinForms listbox that has transparency and multi-line list items, I’ve never been happy with the amount of work required and the end result just never seems quite right. Maybe there is a better way out there somewhere, but I’ve always had to make a custom control, override the paint event, capture the image behind the listbox, do some crazy stuff with scrolling, blah, blah, etc. Since WPF is supposed to make these fancy, cool-looking interfaces (that will likely have extravagant background images), let’s see if it makes it any easier to make transparent multi-line listboxes.
The first order of business after firing up Visual Studio 2008 RC1 is to create a new project to house my stumbling efforts. In the new project dialog, I see four project templates geared towards WPF: WPF Application, WPF User Control Library, WPF Browser Application, and WPF Custom Control Library. I am guessing that the ‘WPF Application’ template is a windows application utilizing WPF, so I’ll select that and name my project ‘StumblingThroughWPFPartI’, in the new ‘StumblingThrough’ solution:

So let’s see what this project template created for me… I see that my project has the normal ‘Properties’ section, and that it has added a few unusual references by default: ‘PresentationCore’, ‘PresentationFramework’, and ‘WindowsBase’. I’m guessing those are the key WPF assemblies. It also added to files to my project: App.xaml and Window1.xaml:

Now I realize that Window1.xaml is probably the default form that most new project templates give you, but what the heck is App.xaml? I’ll dig into that in future posts, I hope, but it doesn’t seem to have anything to do with my quest for the perfect transparent listbox as long as it is set up to run Window1 as the default window, which this line says it is:
StartupUri="Window1.xaml"
All right, now on to my window itself. First things first, I need a background to the window so I can tell if the listbox I eventually add is indeed transparent. I’ve scoured my hard drive, which is still a relatively clean install, and found ‘Greenstone.bmp’, which is probably one of the default windows backgrounds. I’ve copied it into my project folder and added it to the project:

Now the quest becomes referencing this image in the background of my window. My WinForms instincts have me click the window in the designer, and then look for a ‘Background’ or ‘Background Image’ property in the property explorer. Sadly, the ‘Background’ property seems to deal only with colors, not images. Looks like it isn’t going to be as easy as I thought… after searching a bit online, I’ve made the discovery that the ‘Background’ property of a window can be set to a ‘brush’ object, which can be pre-populated with the image that I want to paint. Now I see why this wasn’t available in the property explorer; I need to instantiate an object for the property value!
Again, my WinForms instincts (hereafter referred to as my ‘WinForms Sense’, so I can say ‘My WinForms Senses are tingling’) are telling me to make a form_load event handler, create the brush object in there and set the background property that way. However, I’ve already learned not to trust my WinForms senses so I look for a better way. Turns out that the window design is made up of XAML, or, eXtensible Application Markup Language. Beginners call it X-A-M-L, while those that think they know what they are talking about call it ‘Zamel’. Whatever you decide to call it, it is a rather powerful design tool that is practically another language in itself. I can tell I have a lot to learn here, but I did manage to find out how to set the window’s background equal to a new brush object all within the XAML, here is how:
<Window.Background>
<ImageBrush ImageSource="Greenstone.bmp" />
</Window.Background>
The ‘<Window.Background>’ tag is telling the XAML that whatever I say within that tag is the value for the Window’s Background property. This syntax is particularly useful when you want to set the value of a property to an object, as we need to do in this case. The <ImageBrush ImageSource="Greenstone.bmp" /> tag instantiates an Image Brush object, setting its source to our image file. This is that value then given to the window’s background property, and we can see the results immediately in the designer:

Well that took a whole heck of a lot longer than I thought it would, I haven’t even started the listbox yet! All I have achieved is a simple form with an image for a background, but that is why these blogs are titled ‘Stumbling Through’. I will get to that listbox next time, I need to absorb what I’ve learned here today.