WPF Enums in XAML And Root Addressing For Images

By Robbe Morris

This small code sample demonstrates how to use Enum values in your XAML files. It also includes how to set the image source property in your xaml files to image resources in different assemblies such as the BusinessLogic assembly in this sample.

If your application plans on storing XAML externally from your app and offer extreme styling flexibility to your users, then being able to set icons for various controls is likely to be a requirement for you.  So, just for kicks, I figured I show this quick tip demonstrating how to work with enums in your XAML.


  Download Source Code


<Window x:Class="WPFTutorial.Window1"
    
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
xmlns:enums="clr-namespace:BusinessLogic.Enums;assembly=BusinessLogic"
    
xmlns:data="clr-namespace:BusinessLogic;assembly=BusinessLogic"
    
Title="Window1" Height="518" Width="658" WindowStartupLocation="CenterScreen">
    
    <Window.Resources>
        
           <DataTemplate x:Key="ColumnHeader">
                              
                 <StackPanel Orientation="Horizontal">
                     <TextBlock Text="Candidate"  Margin="3,3,3,3"/>
                 </StackPanel>
                   
         </DataTemplate>
      
         <DataTemplate x:Key="Cell"  DataType="x:Type data:Candidate">
                                
        <StackPanel Orientation="Horizontal">
           <Image  x:Name="Icon" HorizontalAlignment="Right"  Margin="3,3,3,3"
  VerticalAlignment="Bottom" Width="16" Height="16"
                
Source="/BusinessLogic;component/graphics/icons/Republican.gif"
Stretch="Fill" Visibility="Collapsed"/>
                     <TextBlock Text="{Binding Path=CandidateName, Mode=OneWay}"
Margin="3,3,3,3"/>
                 </StackPanel>
                   
               <DataTemplate.Triggers>
                   <DataTrigger Binding="{Binding Path=PoliticalPartyType}">
                     <DataTrigger.Value>
                          <enums:PoliticalPartyTypes>
                              Unknown
                          </enums:PoliticalPartyTypes>
                     </DataTrigger.Value>
                      <Setter TargetName="Icon" Property="Visibility" Value="Hidden"/>
                 </DataTrigger>
                 <DataTrigger Binding="{Binding Path=PoliticalPartyType}">
                     <DataTrigger.Value>
                          <enums:PoliticalPartyTypes>
                              Republican
                          </enums:PoliticalPartyTypes>
                     </DataTrigger.Value>
                        <Setter TargetName="Icon" Property="Source"
Value="/BusinessLogic;component/graphics/icons/republican.gif"/>
                       <Setter TargetName="Icon" Property="Visibility" Value="Visible"/>
                 </DataTrigger>
                   <DataTrigger Binding="{Binding Path=PoliticalPartyType}">
                     <DataTrigger.Value>
                          <enums:PoliticalPartyTypes>
                              Democrat
                          </enums:PoliticalPartyTypes>
                     </DataTrigger.Value>
                        <Setter TargetName="Icon" Property="Source"
Value="/BusinessLogic;component/graphics/icons/democrat.gif"/>
                       <Setter TargetName="Icon" Property="Visibility" Value="Visible"/>
                 </DataTrigger>
                     <DataTrigger Binding="{Binding Path=PoliticalPartyType}">
                     <DataTrigger.Value>
                          <enums:PoliticalPartyTypes>
                              Conservative
                          </enums:PoliticalPartyTypes>
                     </DataTrigger.Value>
                        <Setter TargetName="Icon" Property="Source"
Value="/BusinessLogic;component/graphics/icons/republican.gif"/>
                       <Setter TargetName="Icon" Property="Visibility" Value="Visible"/>
                 </DataTrigger>
               </DataTemplate.Triggers>
         </DataTemplate>
      
        
    </Window.Resources>
    
    
         <ListView Name="ListTemplates" Width="Auto" Height="Auto"
VerticalAlignment="Stretch"  HorizontalAlignment="Stretch">
             <ListView.View>
               <GridView>
                   <GridViewColumn Header="Candidate Name"
HeaderTemplate="{StaticResource ColumnHeader}"
CellTemplate="{DynamicResource Cell}"  />
               </GridView>
              </ListView.View>
               <ListView.ItemContainerStyle>
                     <Style TargetType="{x:Type ListViewItem}">
                           <Setter Property="HorizontalContentAlignment"
Value="Stretch" />
                     </Style>
               </ListView.ItemContainerStyle>
             </ListView>
</Window>




// Code behind

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows.Threading;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using BusinessLogic;
using BusinessLogic.Enums;

namespace WPFTutorial
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        public Window1()
        {
             InitializeComponent();
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }

        private void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            LoadCandidates();
            this.ListTemplates.ItemsSource = CandidateList;
        }

        private void LoadCandidates()
        {
            ObservableCollection<Candidate>  list = new ObservableCollection<Candidate>();
             list.Add(new Candidate(0, "2008", "Candidates", (int)PoliticalPartyTypes.Republican));
             list.Add(new Candidate(1, "John", "McCain", (int)PoliticalPartyTypes.Republican));
             list.Add(new Candidate(2, "Lord", "Obama", (int)PoliticalPartyTypes.Democrat));
             list.Add(new Candidate(3, "Robbe", "Morris", (int)PoliticalPartyTypes.Conservative));

             this.CandidateList = list;
        }

        private ObservableCollection<Candidate> _candidateList = null;
        public ObservableCollection<Candidate> CandidateList
        {
            get
            {
                 return _candidateList;
            }
            set
            {
                _candidateList = value;
                 OnPropertyChanged("CandidateList");
            }
        }

        private Candidate _selectedCandidate;
        public Candidate SelectedCandidate
        {
            get { return _selectedCandidate; }
            set
            {
                _selectedCandidate = value;

                 OnPropertyChanged("SelectedCandidate");
            }
        }
  
        public event PropertyChangedEventHandler PropertyChanged;

         protected void OnPropertyChanged(string propertyName)
        {
             if (PropertyChanged == null) { return; }
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
      

    }
}



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BusinessLogic
{
    public class Candidate
    {

         public Candidate(int candidateID, string firstName, string lastName, int politicalPartyID)
        {
            _candidateID = candidateID;
            _firstName = firstName;
            _lastName = lastName;
            _politicalPartyTypeID = politicalPartyID;
        }

        private int _candidateID = 0;
        public int CandidateID
        {
            get { return _candidateID; }
            set { _candidateID = value; }
        }

         public string CandidateName
        {
            get { return FirstName + " " + LastName; }
        }

        private string _firstName = string.Empty;
        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value.Trim(); }
        }

        private string _lastName = string.Empty;
        public string LastName
        {
            get { return _lastName; }
            set { _lastName = value.Trim(); }
        }

        private int _politicalPartyTypeID = 0;
        public int PoliticalPartyTypeID
        {
            get { return _politicalPartyTypeID; }
            set { _politicalPartyTypeID = value; }
        }

         public Enums.PoliticalPartyTypes PoliticalPartyType
        {
            get { return (Enums.PoliticalPartyTypes)_politicalPartyTypeID; }
         }

    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BusinessLogic.Enums
{

    public enum PoliticalPartyTypes : int
    {
       Unknown = 0,
        Republican = 1,
        Democrat = 2,
        Conservative = 3
    }
    
}
Popularity  (3769 Views)
Picture
Biography - Robbe Morris
Robbe has been a Microsoft MVP in C# since 2004. He is also the co-founder of EggHeadCafe.com which provides .NET articles, book reviews, software reviews, and software download and purchase advice.  Robbe also loves to scuba dive and go deep sea fishing in the Florida Keys or off the coast of Daytona Beach. Microsoft MVP
Create New Account
Article Discussion: WPF - Silverlight Enums in XAML And Root Addressing For Images
Robbe Morris posted at Thursday, September 04, 2008 8:02 PM
Michael Pokerschnig replied to Robbe Morris at Wednesday, October 20, 2010 10:39 AM
I tested code similar to yours defining my enum in an extra sub namespace like you did it and all works fine now.But I can not understand why the same enum defined 1 namespace upper does not work.
I get an error that the property 'Value' of datatrigger can not accept values of this enum type.

For me it is the same situation just a different namespace ?
Robbe Morris replied to Michael Pokerschnig at Wednesday, October 20, 2010 10:39 AM
"same enum defined 1 namespace upper"
 
I do not understand what you mean by this.  You may want to post some of your code.
Michael Pokerschnig replied to Robbe Morris at Wednesday, October 20, 2010 10:39 AM
<[default] http://schemas.microsoft.com/winfx/2006/xaml/presentation:UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:viewModelEnums="clr-namespace:SPA.Arion.OutputWPF.ViewModel.Enums" xmlns:viewModel="clr-namespace:SPA.Arion.OutputWPF.ViewModel" xmlns:view="clr-namespace:SPA.Arion.OutputWPF.View" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SPA.Arion.OutputWPF.View.JobWizardView">

<

 

UserControl x:Class="SPA.Arion.OutputWPF.View.JobWizardView"

 

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

 

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

 

  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

 

  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

 

  xmlns:view="clr-namespace:SPA.Arion.OutputWPF.View"

 

  xmlns:viewModel="clr-namespace:SPA.Arion.OutputWPF.ViewModel"

 

  xmlns:viewModelEnums="clr-namespace:SPA.Arion.OutputWPF.ViewModel.Enums">

 

 

 

<UserControl.Resources>

 

<!-- WIZARD STEP TEMPLATE for SmartGUI -->

 

 

<DataTemplate x:Key="wizardStepTemplateSmart">

 

 

<Grid>

 

 

  <Path x:Name="frame" Margin="8,0" Stroke="Gray" StrokeThickness="2" StrokeMiterLimit="1.0" Data="F1 M 0,0 L 100,10 L 200,0 L200,50 L100,60 L0,50 Z"/>

 

 

 

 

 

  <TextBlock x:Name="txt" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10" Foreground="Gray" Text="{Binding Path=DisplayName}"/>

 

 

</Grid>

 

 

 

 

 

<DataTemplate.Triggers>

 

 

  <DataTrigger Binding="{Binding Path=IsCurrentPage}" Value="True">

 

 

  <Setter TargetName="txt" Property="FontWeight" Value="Bold"/>

 

 

  <Setter TargetName="txt" Property="Foreground" Value="{StaticResource SPG_Blue_Medium_Brush}"/>

 

 

  <Setter TargetName="frame" Property="Stroke" Value="{StaticResource SPG_Blue_Medium_Brush}"/>

 

 

  <Setter TargetName="frame" Property="Effect">

 

 

    <Setter.Value>

 

 

      <DropShadowEffect Color="{StaticResource SPG_Blue_Dark}" BlurRadius="10" ShadowDepth="0"/>

 

 

    </Setter.Value>

 

 

  </Setter>

 

 

</DataTrigger>

 

 

  <DataTrigger Binding="{Binding Path=PageSequence}">

 

 

    <DataTrigger.Value>

 

 

      <viewModelEnums:EPageSequenceType>First</viewModelEnums:EPageSequenceType>

 

 

    </DataTrigger.Value>

 

 

  <Setter TargetName="frame" Property="Data" Value="F1 M 0,0 L 200,0 L200,50 L100,60 L0,50 Z"/>

 

 

</DataTrigger>

 

 

 

 

 

 

</DataTemplate>

code where enum is decalred now:

namespace

 

 

 

 

SPA.Arion.OutputWPF.ViewModel

{

 

 

 

 

  namespace Enums

  {

 

 

 

 

    public enum EPageSequenceType : int  

    {

      First = 0,

      Middle = 1,

      Last = 2

    }

  }

 

 

 

 

 

  public abstract class JobWizardPageBaseVM : ViewModelBase

  {

 

 

    #region

 

 

Members

 

 

 

    bool _isCurrentPage = false;

 

 

 

    bool _isSmartGUI = true;

    Enums.

 

 

EPageSequenceType m_PageSequence = Enums.EPageSequenceType.Middle;

    .

    .

    .

  }

}

 

If I declare EPageSequenceType in the namespace SPA.Arion.OutputWPF.ViewModel.Enums all works (its verry similar to your example), but if I had it decalred at SPA.Arion.OutputWPF.ViewModel then I get an error at visual studio XAML-Designer.

I wanted to reporduce it now to give you the detailed error message but not it works!

As I have a source control system I'm quite shure the same code did give me the error before but I think the VS2010 XAML-Designer is sometimes now working correctly. Maybe we have problems with VS2010 Designer as we are developing on x64 for x64 and XAML-Designer is 32 bit.

Sorry for that ;)