It’s way too hard to get an image next to the text content of a Button, TextBlock, ListBoxItem, TreeViewItem, etc. Coming from a Windows Forms background where many controls had an Image property for displaying a small glyph next to text content, I am constantly frustrated by the verbose XAML required to achieve the same in WPF and Silverlight.
<StackPanel>
<Button>
<DockPanel>
<Image Source="Images/Alert.png" />
<TextBlock Text="Alerts" />
</DockPanel>
</Button>
<Button>
<DockPanel>
<Image Source="Images/Color-Blue.png" />
<TextBlock Text="Blue Category" />
</DockPanel>
</Button>
<Button>
<DockPanel>
<Image Source="Images/Color-Green.png" />
<TextBlock Text="Green Category" />
</DockPanel>
</Button>
<Button>
<DockPanel>
<Image Source="Images/Color-Red.png" />
<TextBlock Text="Red Category" />
</DockPanel>
</Button>
</StackPanel>
Well using a WPF markup extension in XAML we can make the code look a little less clunky. Markup extensions (which derive from System.Windows.MarkupExtension) are instantiated similarly to the way attributes are declared in C#. That is to say, there can be positional and/or named parameters. By overriding the ProvideValue you can use those parameters to construct whatever object structure you want and return it. The XAML parser will use this in place of your markup extension when it finds it.
<StackPanel>
<Button Content="{e:Content Alerts, Image=Images/Alert.png}" />
<Button Content="{e:Content Blue Category, Image=Images/Color-Blue.png}" />
<Button Content="{e:Content Green Category, Image=Images/Color-Green.png}" />
<Button Content="{e:Content Red Category, Image=Images/Color-Red.png}" />
</StackPanel>
Unfortunately Silverlight does not allow you to create custom markup extensions yet so this same technique cannot be applied to Silverlight where the situation is arguably worse with all the toolkit namespaces and such.
The code for the ContentExtension is very straightforward so I’m just going to add it to the end of the post instead of going through the hassle of uploading a project. Enjoy.
/// <summary>
/// A XAML Markup Extension that allows you to combine simple text content with an image
/// alongside instead of having to manually nest the image and text in a panel.
/// </summary>
public class ContentExtension : MarkupExtension
{
// constructor with positional parameter
public ContentExtension( string text )
{
Text = text;
}
// image must be specified as a named parameter
public ImageSource Image
{
get;
set;
}
public string Text
{
get;
set;
}
public override object ProvideValue( IServiceProvider serviceProvider )
{
return new DockPanel {
Children = {
new Image {
Source = Image,
Stretch = Stretch.None,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
Margin = new Thickness( 5 )
},
new TextBlock {
VerticalAlignment = VerticalAlignment.Center,
Text = Text
}
}
};
}
} // class


Posts