title: Binding data to an IValueConverter for a Silverlight ComboBox
body: <p>I have a ComboBox that allows the user to select an hourly offset (0, 3, 6 or 9). However, what they see needs to be shown as an absolute time, which is derived by adding the offset to a base time. e.g. if the base time is "0600", the user gets to choose from "0600", "0900", "1200" and "1500".</p>
  
  <p>I'm using an IValueConverter to convert this offset time to an absolute time  The base time is passed to the converter by binding a value to a custom property of the converter. (see below for the code).</p>
  
  <p>Now this generally works fine except for the case of the initially selected value in the ComboBox; this always uses the default BaseTime of UtcNow, and doesn't use the bound value. By setting breakpoints in the code I can see that the BaseTime dependency property isn't set until after the call to Convert whch converts the initial value.</p>
  
  <p>This is the converter class I'm using:</p>
  
  <pre><code>public class ForecastTimeConverter : DependencyObject, IValueConverter
  {
       // Register the dependency property we need for the BaseTime property.
       public DependencyProperty BaseTimeProperty = DependencyProperty.Register(
              "BaseTime", 
              typeof(DateTime), 
              typeof(ForecastTimeConverter),
              new PropertyMetadata(DateTime.UtcNow, BaseTimeChanged)
         );
  
      private static void BaseTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
              // this method here just so I can set a breakpoint to see when the property is set.
      }
  
      public DateTime BaseTime
      {
          get { return (DateTime)GetValue(BaseTimeProperty);}
          set { SetValue(BaseTimeProperty, value); }
      }
  
      public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
          string forecast_time;
          if (value is string)
          {
              try
              {
                  // get forecast period, in hours.
                  int hours = System.Convert.ToInt32(value as string);
                  // add forecast period to base time to get final forecast time.
                  DateTime forecastTime = BaseTime + new TimeSpan(hours, 0, 0);
                  forecast_time = String.Format("{0:HHmm}z", forecastTime);
              }
              catch
              {
                  forecast_time = "?";
              }    
          }
          else
          {
              throw new NotImplementedException("Can't convert from type '" + typeof(ValueType) + "'");
          }
          return forecast_time;
      }
  
      public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
          throw new NotImplementedException();
      }
  }
  </code></pre>
  
  <p>The full XAML and UserControl source is rather large, so here are just the relevant bits:</p>
  
  <pre><code>&lt;UserControl.Resources&gt;
      &lt;status:ForecastTimeConverter x:Key="ForecastTimeConverter" BaseTime="{Binding Path=CurrentBaseTime}" /&gt;
  &lt;/UserControl.Resources&gt;
  ...
  &lt;ComboBox x:Name="forecastPeriodCombo" Grid.Row="0" Grid.Column="1" Width="100" SelectionChanged="OnforecastPeriodChanged" &gt;
      &lt;ComboBox.ItemTemplate&gt;
          &lt;DataTemplate&gt;
              &lt;TextBlock Text="{Binding Converter={StaticResource ForecastTimeConverter}}"/&gt;
          &lt;/DataTemplate&gt;
      &lt;/ComboBox.ItemTemplate&gt;
  &lt;/ComboBox&gt;
  </code></pre>
  
  <p>And the relevant code behind the XAML, simplified:</p>
  
  <pre><code>public partial class MyControl : UserControl
  {
      public MyControl()
      {
          InitializeComponent();
          this.Loaded += OnLoaded;
      }
  
      public void OnLoaded(object sender, EventArgs e)
      {
          forecastPeriodCombo.Items.Clear();
          List&lt;string&gt; values = new List&lt;string&gt;();
          values.Add("0");
          values.Add("3");
          values.Add("6");
          values.Add("9");
          forecastPeriodCombo.ItemsSource = values;
          forecastPeriodCombo.SelectedIndex = 1;
      }
  }
  </code></pre>
  
  <p>The problem is that the binding of the BaseTime property of the converter isn't done until <em>after</em> the Loaded event fires for the UserControl, so the when the ComboBox is displayed, instead of seeing "0900" (3hrs offset from BaseTime) as the current value, I see something more like "17:47", (3 hours offset from UtcNow).  When I click on the ComboBox the drop-down is populated with the correct times. It's just the initial value that is wrong due to the order of events.</p>
  
  <p>OnLoaded is called, ComboBox is filled, SelectedIndex is set, Convert is called, <em>then</em> the BaseTime property of the convert is set (too late!).</p>
  
  <p>How can I acheive the effect I require?  Should I be populating the ComboBox on some other event? Or is there perhaps a better way to pass the basetime to the converter?</p>