Icons and icon buttons

When the new style for Smart Office was introduced in version 10.1.0 we also added a new set of icons. There are now almost two hundred icons that can be used on buttons, menus or to convey information in an application. In addition to the new icons a couple of controls were added to make it easy to use the icons. These new controls are the Icon, IconButton and CommandBarButton in the Mango.DesignSystem namespace.

Icon viewer Mashup

Before we can start using the icons we need to know what icons are available to us. The names of all the icons are defined in an enumeration called IconNames in the Mango.DesignSystem namespace. Some of the icon names are quite obvious such as “Open” and “Save” and you will know directly when to use them. Other icons names are less common and in these cases it would be nice to have a visual overview of all the icons. To solve this I will build a simple Icon viewer using a Mashup.

Starting with a new XAML file in the Mashup Designer I first need to add some namespace declarations. The Mango.DesignSystem namespace must be included for the IconName enumeration and the Icon class. To be able to list the icons I also need the System and System.ComponentModel namespaces. The required namespace declarations can be seen below.

xmlns:ds="clr-namespace:Mango.DesignSystem;assembly=DesignSystem" 
xmlns:sys="clr-namespace:System;assembly=mscorlib" 
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"

The next step is to get a list of the icon names. To do this I need to call a static method called GetNames on the Enum class. The GetNames method requires an enum type, in this case IconName. The ObjectDataProvider class lets me call the method and by wrapping that in a CollectionViewSource I get a list of icon names sorted alphabetically.

Now that I have a list of icon names I can create a ListBox to display the icons in. I want the icons to wrap so I change the ItemsPanel to a WrapPanel. The DataTemplate for the ListBox is also set since I want to display both the icon and the icon name. The Icon class is used to show the icon by setting the IconName property. This property is actually an enum of the type IconName but the binding to the icon name as a string still works using the built-in enum conversion in WPF.

Some of the icon names are a bit long so the width of each item is limited. To see the full name of an icon there is a tooltip and the label under the icon is also selectable so that the icon name can be copied.

This is a screenshot of the Icon viewer with all icons visible.
ICN_IconView

Here is the source code for the Icon viewer.

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="clr-namespace:Mango.UI.Controls;assembly=Mango.UI" xmlns:mashup="clr-namespace:Mango.UI.Services.Mashup;assembly=Mango.UI" xmlns:ds="clr-namespace:Mango.DesignSystem;assembly=DesignSystem" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase">
   
   <Grid.Resources>
      <CollectionViewSource x:Key="sortedIconNames">
         <CollectionViewSource.SortDescriptions>
            <scm:SortDescription />
         </CollectionViewSource.SortDescriptions>
         <CollectionViewSource.Source>
            <ObjectDataProvider MethodName="GetNames" ObjectType="{x:Type sys:Enum}" x:Key="iconNames">
               <ObjectDataProvider.MethodParameters>
                  <x:Type TypeName="ds:IconName" />
               </ObjectDataProvider.MethodParameters>
            </ObjectDataProvider>
         </CollectionViewSource.Source>
      </CollectionViewSource>
   </Grid.Resources>

   <ListBox ItemsSource="{Binding Source={StaticResource sortedIconNames}}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
      <ListBox.ItemsPanel>
         <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal" />
         </ItemsPanelTemplate>
      </ListBox.ItemsPanel>
      <ListBox.ItemTemplate>
         <DataTemplate>
            <StackPanel Orientation="Vertical" Margin="2" Width="80" ToolTip="{Binding}">
               <ds:Icon IconName="{Binding}" HorizontalAlignment="Center" />
               <TextBox IsReadOnly="True" Background="Transparent" BorderThickness="0" Padding="0" Margin="0,4,0,0" Text="{Binding Path=., StringFormat=G}" HorizontalAlignment="Center" />
            </StackPanel>
         </DataTemplate>
      </ListBox.ItemTemplate>
   </ListBox>

</Grid>

Icon buttons

All the icons that are defined in the IconName enum can easily be used with two different button controls called IconButton and CommandBarButton. The IconButton is a button control with only an icon. The CommandBarButton is an extension of the IconButton that adds support for text that can be placed besides or under the icon.

To show how to use these buttons I will create small command bar with a couple of actions. For the primary actions, “Open” and “Save”, I will use the CommandBarButton class and set a text that is displayed to the left of the icons. To display the text on the left the CommandBarButtonMode property is set to “SelectiveLabels”. To display the text under the icons I could have used the “AllLabels” mode. There is also an “OnlyIcons” mode that is basically the same as just using an IconButton. The reason for these three modes is that an application may choose to have a user setting that controls this behavior.

In addition to the CommandBarButtons I’ll add three more commands that only shows an icon and for these I use the IconButton class. To get consistent alignment and margins I set the Padding property to zero for all controls and set the Margin properties using static values in the Margins class. The Margins class was added in Smart Office 10.1.0 and can be used to get consistent margins in an application. I use the medium margin between most of the buttons but use the extra large margin as a separator between the CommandBarButton controls with the text and the IconButton controls.

The result can be seen in the screenshot below. Note that the mouse pointer was over the Open button when the screenshot was taken so the mouse over effect with the theme accent color can be seen.

ICN_IconButtons

Here is the source code for the command bar example.

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="clr-namespace:Mango.UI.Controls;assembly=Mango.UI" xmlns:mashup="clr-namespace:Mango.UI.Services.Mashup;assembly=Mango.UI" xmlns:ds="clr-namespace:Mango.DesignSystem;assembly=DesignSystem">

   <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left">
      <ds:CommandBarButton IconName="Open" CommandBarButtonMode="SelectiveLabels" Content="Open" Padding="0" />
      <ds:CommandBarButton IconName="Save" CommandBarButtonMode="SelectiveLabels" Content="Save" Padding="0" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:IconButton IconName="Refresh" Padding="0" Margin="{x:Static ds:Margins.ThicknessExtraLargeLeft}" />
      <ds:IconButton IconName="Search" Padding="0" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:IconButton IconName="Print" Padding="0" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
   </StackPanel>

</Grid>

Icon customization

The color and size of the icons can be customized just by setting properties on the Icon, IconButton and CommandBarButton classes. It is also possible to create new icons that can be used by these classes but that is a topic for another post.

The easiest thing to customize is the color of the icon. Just set the IconBrush property to change the default color. In the example below I have used some hardcoded colors but in most cases you should probably use a color brush defined in a shared resource dictionary.

The other thing that can be customized is the size of the icon. The default icon size is 18×18 pixels and this corresponds to the physical size of the icon image files. The size of the icons can be changed to anything you like but you need to consider scaling artifacts in the images. If scaled within reason the results looks OK but if the icons are scaled too large the images will be distorted. Downscaling the icons are more forgiving but there can be issues there as well.

To change the size of an icon you need to set three properties and the property names are not the same for all classes. For the Icon class set the Stretch, Width and Height properties. For the IconButton class and the CommandBarButton class set the IconStretch, IconWidth and IconHeight properties. The Icon class is just a subclass of the Image class so there we could reuse the existing properties but for the button controls we needed to add new properties.

The Stretch/IconStetch property should be set to “Uniform” and the Width/Height or IconWidth/IconHeight properties to desired size. In most cases you should use the same value for both width and height unless you want to achieve some special effect using a different value for the stretch setting.

The example below shows how to set different sizes on the Icon class using the “Home” icon and the IconButton class using the “Settings” icon. The middle icon uses the default size and the others gets 4 pixels smaller or larger.

ICN_IconCustomization

Here is the source code for the icon customization example.

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="clr-namespace:Mango.UI.Controls;assembly=Mango.UI" xmlns:mashup="clr-namespace:Mango.UI.Services.Mashup;assembly=Mango.UI" xmlns:ds="clr-namespace:Mango.DesignSystem;assembly=DesignSystem">
   <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="15" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="15" />
      <RowDefinition Height="Auto" />
   </Grid.RowDefinitions>
   <Grid.ColumnDefinitions>
      <ColumnDefinition Width="1*" />
   </Grid.ColumnDefinitions>

   <StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left">
      <ds:Icon IconName="Home" IconBrush="#13a3f7" />
      <ds:Icon IconName="Search" IconBrush="#2db329" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="Print" IconBrush="#ffaa00" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="Settings" IconBrush="#d5000e" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="Padlock" IconBrush="#e63262" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="Mail" IconBrush="#a352cc" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="Favorite" IconBrush="#737373" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="User" IconBrush="#00c2b4" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
   </StackPanel>

   <StackPanel Grid.Row="2" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left">
      <ds:Icon IconName="Home" Stretch="Uniform" Width="10" Height="10" />
      <ds:Icon IconName="Home" Stretch="Uniform" Width="14" Height="14" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="Home" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="Home" Stretch="Uniform" Width="22" Height="22" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:Icon IconName="Home" Stretch="Uniform" Width="26" Height="26" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
   </StackPanel>

   <StackPanel Grid.Row="4" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left">
      <ds:IconButton IconName="Settings" IconStretch="Uniform" IconWidth="10" IconHeight="10" />
      <ds:IconButton IconName="Settings" IconStretch="Uniform" IconWidth="14" IconHeight="14" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:IconButton IconName="Settings" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:IconButton IconName="Settings" IconStretch="Uniform" IconWidth="22" IconHeight="22" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
      <ds:IconButton IconName="Settings" IconStretch="Uniform" IconWidth="26" IconHeight="26" Margin="{x:Static ds:Margins.ThicknessMediumLeft}" />
   </StackPanel>

</Grid>

7 thoughts on “Icons and icon buttons

  1. Pingback: Lawson Design System | Developing for Infor Smart Office

  2. Pingback: Hacking Customer Lifecycle Management (CLM) | M3 ideas

  3. Thomas Bateup

    Hello,
    How would I assign an Event to an Icon that I have implemented in a Mashup using the ds:CommandBarButton code above?

    I have tried using the same syntax as with a regular button i.e.

    but to no avail.

    Could you advise where I am going wrong?

  4. Thomas Bateup

    I did try to leave some example code in my previous post but it appears to have been chopped from the above post.

  5. Pingback: Mashup quality control #2 – M3 ideas

  6. Qasim

    You mention in your post that you can customize your own icons,
    how can you do this, is there a guide.
    also what can I upload my own icons and use them in mashup’s

    1. Karin Portillo

      Hi, Please see the startPad example for a way to include icons, https://smartofficeblog.com/2011/09/05/how-to-create-a-start-pad-mashup/. In that example icons were added to the mashup zip itself. As for these build in SoHoXi icons you can’t add your own in an easy manner. You would have to use the image approach, but there are a lot of options that you can use in just plain WPF, create your own styling or just add the image.

      It is also possible to create new icons that can be used by these classes but as the blog says it would take some time to go through that example and I don’t have the time to research and write that down.

Comments are closed.