Sunday, 5 October 2008

WPF ComboBox Data Binding

Binding a enum property (PaymentFrequency) to a WPF ComboBox.
This property provides the ItemsSource for the combobox by building a dictionary of enum (key) and enum.ToString (value).
   public enum PaymentFrequency
   {
      DayOfPlay,
      Monthly,
      None,
      Quarterly,
      Weekly,
   }
Expose this as a Property and Dictionary for Binding purposes:
      public PaymentFrequency Frequency { get; set; }

      public IDictionary<PaymentFrequency, string> FrequencyList
      {
         get
         {
            IDictionary<PaymentFrequency, string> frequencyList = new Dictionary<PaymentFrequency, string>();
            foreach (PaymentFrequency pf in Enum.GetValues(typeof(PaymentFrequency)))
            {
               frequencyList.Add(pf, pf.ToString());
            }
            return frequencyList;
         }
      }
The corresponding xaml (not forgetting the UpdateSourceTrigger=PropertyChanged if the ComboBox is inside a DataGrid as discussed here):
      <ComboBox ItemsSource="{Binding Path=FrequencyList, Mode=OneTime}"
                SelectedValuePath="Key"
                DisplayMemberPath="Value"
                SelectedValue="{Binding Path=Frequency, UpdateSourceTrigger=PropertyChanged}">
      </ComboBox>
For Internationalisation purposes it would be better to use Resource Strings to provide the descriptions for the combobox. I used a prefix of "PF_" on all the strings to ensure they are unique:

PF_DayOfPlay Day of Play 
PF_Monthly Monthly 
PF_None  None 
PF_Quarterly Quarterly 
PF_Weekly Weekly
Then modify the FrequencyList getter:
      public PaymentFrequency Frequency { get; set; }

      public IDictionary<PaymentFrequency, string> FrequencyList
      {
         get
         {
            IDictionary<PaymentFrequency, string> frequencyList = new Dictionary<PaymentFrequency, string>();
            foreach (PaymentFrequency pf in Enum.GetValues(typeof(PaymentFrequency)))
            {
               frequencyList.Add(pf, ResourceStrings.ResourceManager.GetString("PF_" + pf.ToString()));
            }
            return frequencyList;
         }
      }
A final tweak is to sort the descriptions displayed in the combobox into alphabetic order based on the translated strings.
      public PaymentFrequency Frequency { get; set; }

      public IDictionary<PaymentFrequency, string> FrequencyList
      {
         get
         {
            IDictionary<PaymentFrequency, string> frequencyList = new Dictionary<PaymentFrequency, string>();
            foreach (PaymentFrequency pf in Enum.GetValues(typeof(PaymentFrequency)))
            {
               frequencyList.Add(pf, ResourceStrings.ResourceManager.GetString("PF_" + pf.ToString()));
            }
            return frequencyList.OrderBy(f => f.Value).ToDictionary(f => f.Key, f => f.Value);
         }
      }
The ComboboxDataBinding example project includes this code and can be downloaded from GoogleCode.

No comments: