title: Windows Phone ControlTemplate & Converter : problem loading BitmapImage from Image Resource in assembly
body: <p>This is basically a follow up to my <a href="https://stackoverflow.com/questions/6667916/windows-phone-7-image-checkbox">previous</a> question.
  I've managed to make this work with the templates, however, I want to make it a bit generic, so that I don't have to go around repeating code all over the place</p>
  
  <p>The working version (hardcoded) is this :</p>
  
  <pre><code>    &lt;UserControl.Resources&gt;
          &lt;ControlTemplate x:Key="TrebleCheckboxImageTemplate" TargetType="CheckBox"&gt;
              &lt;Image x:Name="imgTreble" MinWidth="100" Source="Images/treble_checked.png"&gt;
                  &lt;VisualStateManager.VisualStateGroups&gt;
                      &lt;VisualStateGroup x:Name="CheckStates"&gt;
                          &lt;VisualState x:Name="Checked"&gt;
                              &lt;Storyboard&gt;
                                      &lt;ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imgTreble" Storyboard.TargetProperty="(Image.Source)"&gt;
                                          &lt;DiscreteObjectKeyFrame KeyTime="00:00:00"&gt;
                                                  &lt;DiscreteObjectKeyFrame.Value&gt;
                                                          &lt;BitmapImage UriSource="Images/treble_checked.png" /&gt;
                                                  &lt;/DiscreteObjectKeyFrame.Value&gt;
                                          &lt;/DiscreteObjectKeyFrame&gt;
                                      &lt;/ObjectAnimationUsingKeyFrames&gt;
                                  &lt;/Storyboard&gt;
                          &lt;/VisualState&gt;
                          &lt;VisualState x:Name="Unchecked"&gt;
                              &lt;Storyboard&gt;
                                  &lt;ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imgTreble" Storyboard.TargetProperty="(Image.Source)"&gt;
                                      &lt;DiscreteObjectKeyFrame KeyTime="00:00:00"&gt;
                                              &lt;DiscreteObjectKeyFrame.Value&gt;
                                                      &lt;BitmapImage UriSource="Images/treble_unchecked.png" /&gt;
                                              &lt;/DiscreteObjectKeyFrame.Value&gt;
                                      &lt;/DiscreteObjectKeyFrame&gt;
                                      &lt;/ObjectAnimationUsingKeyFrames&gt;
                              &lt;/Storyboard&gt;                           
                          &lt;/VisualState&gt;
                          &lt;VisualState x:Name="Indeterminate"/&gt;
                      &lt;/VisualStateGroup&gt;
                  &lt;/VisualStateManager.VisualStateGroups&gt;
              &lt;/Image&gt;
  
          &lt;/ControlTemplate&gt;
      &lt;/UserControl.Resources&gt;
  
  
  &lt;StackPanel x:Name="LayoutRoot" Background="{StaticResource PhoneForegroundBrush}" Orientation="Horizontal"&gt;
          &lt;CheckBox Height="72" HorizontalAlignment="Left" Background="White" VerticalAlignment="Top" Template="{StaticResource TrebleCheckboxImageTemplate}" Margin="0,0,10,0" &gt;
              &lt;Custom:Interaction.Triggers&gt;
                  &lt;Custom:EventTrigger EventName="Click"&gt;
                      &lt;GalaSoft_MvvmLight_Command:EventToCommand CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Command="{Binding TreblePressedCommand}"/&gt;
                  &lt;/Custom:EventTrigger&gt;
              &lt;/Custom:Interaction.Triggers&gt;
          &lt;/CheckBox&gt;
  
      &lt;/StackPanel&gt;
  </code></pre>
  
  <p>Of course, the image paths are hardcoded. So, i wanted to make it generic, so that you could just instantiate a checkbox, tell it it's image, and the template would be the same for all.</p>
  
  <p>I created an ImageCheckbox control class :</p>
  
  <pre><code>public class ImageCheckbox : CheckBox
      {
  
          /// &lt;summary&gt;
          /// The &lt;see cref="CheckedImagePath" /&gt; dependency property's name.
          /// &lt;/summary&gt;
          public const string CheckedImagePathPropertyName = "CheckedImagePath";
  
          /// &lt;summary&gt;
          /// Gets or sets the value of the &lt;see cref="CheckedImagePath" /&gt;
          /// property. This is a dependency property.
          /// &lt;/summary&gt;
          public string CheckedImagePath
          {
              get
              {
                  return (string)GetValue(CheckedImagePathProperty);
              }
              set
              {
                  SetValue(CheckedImagePathProperty, value);
              }
          }
  
          /// &lt;summary&gt;
          /// Identifies the &lt;see cref="CheckedImagePath" /&gt; dependency property.
          /// &lt;/summary&gt;
          public static readonly DependencyProperty CheckedImagePathProperty = DependencyProperty.Register(
              CheckedImagePathPropertyName,
              typeof(string),
              typeof(ImageCheckbox),
              new PropertyMetadata(null));
  
  
          /// &lt;summary&gt;
          /// The &lt;see cref="UnCheckedImagePath" /&gt; dependency property's name.
          /// &lt;/summary&gt;
          public const string UnCheckedImagePathPropertyName = "UnCheckedImagePath";
  
          /// &lt;summary&gt;
          /// Gets or sets the value of the &lt;see cref="UnCheckedImagePath" /&gt;
          /// property. This is a dependency property.
          /// &lt;/summary&gt;
          public string UnCheckedImagePath
          {
              get
              {
                  return (string)GetValue(UnCheckedImagePathProperty);
              }
              set
              {
                  SetValue(UnCheckedImagePathProperty, value);
              }
          }
  
          /// &lt;summary&gt;
          /// Identifies the &lt;see cref="UnCheckedImagePath" /&gt; dependency property.
          /// &lt;/summary&gt;
          public static readonly DependencyProperty UnCheckedImagePathProperty = DependencyProperty.Register(
              UnCheckedImagePathPropertyName,
              typeof(string),
              typeof(ImageCheckbox),
              new PropertyMetadata(null));
  
  
      }
  </code></pre>
  
  <p>I created a converter (because I ran into the problem that I must convert the string to be the Uri for the image source)</p>
  
  <pre><code>public class StringToImageConverter : IValueConverter
      {
          public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
          {
              if (value == null)
              {
                  return null;
              }
  
              if (!UriParser.IsKnownScheme("pack"))
              {
                  UriParser.Register(new GenericUriParser
                      (GenericUriParserOptions.GenericAuthority), "pack", -1);
              }
  
              if (value is string)
              {
                  var image = new BitmapImage();
                  image.UriSource = new Uri(String.Format(@"pack://application:,,/Images/{0}", value as string));
                  //image.UriSource = new Uri(String.Format(@"pack://application:,,,/Adagio.Presentation;component/Images/{0}", value as string),UriKind.Absolute);
                  image.ImageFailed += new EventHandler&lt;System.Windows.ExceptionRoutedEventArgs&gt;(image_ImageFailed);
                  image.ImageOpened += new EventHandler&lt;System.Windows.RoutedEventArgs&gt;(image_ImageOpened);
                  return image;
              }
  
              if (value is Uri)
              {
                  var bi = new BitmapImage {UriSource = (Uri) value};
                  return bi;
              }
              return null;
          }
  
          void image_ImageOpened(object sender, System.Windows.RoutedEventArgs e)
          {
              throw new NotImplementedException();
          }
  
          void image_ImageFailed(object sender, System.Windows.ExceptionRoutedEventArgs e)
          {
              throw new NotImplementedException();
          }
  
          public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
          {
              throw new NotImplementedException();
          }
      }
  </code></pre>
  
  <p>you can see that the converter has been tried with thousands of different combinations, none of them work...
  Then, the new xaml :</p>
  
  <pre><code>&lt;ControlTemplate x:Key="CheckboxImageTemplate" TargetType="Controls:ImageCheckbox"&gt;
              &lt;Image x:Name="imgForTemplate" MinWidth="100" Source="{Binding RelativeSource={RelativeSource TemplatedParent},Path=CheckedImagePath, Converter={StaticResource stringToImageConverter}}"&gt;
                  &lt;!--
                  &lt;VisualStateManager.VisualStateGroups&gt;
                      &lt;VisualStateGroup x:Name="CheckStates"&gt;
                          &lt;VisualState x:Name="Checked"&gt;
                              &lt;Storyboard&gt;
                                  &lt;ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imgForTemplate"  Storyboard.TargetProperty="(Image.Source)"&gt;
                                      &lt;DiscreteObjectKeyFrame KeyTime="00:00:00"&gt;
                                          &lt;DiscreteObjectKeyFrame.Value&gt;
                                              &lt;BitmapImage UriSource="{Binding RelativeSource={RelativeSource TemplatedParent},Path=CheckedImagePath, Converter={StaticResource stringToImageConverter}}" /&gt;
                                          &lt;/DiscreteObjectKeyFrame.Value&gt;
                                      &lt;/DiscreteObjectKeyFrame&gt;
                                  &lt;/ObjectAnimationUsingKeyFrames&gt;
                              &lt;/Storyboard&gt;
                          &lt;/VisualState&gt;
                          &lt;VisualState x:Name="Unchecked"&gt;
                              &lt;Storyboard&gt;
                                  &lt;ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imgForTemplate" Storyboard.TargetProperty="(Image.Source)"&gt;
                                      &lt;DiscreteObjectKeyFrame KeyTime="00:00:00"&gt;
                                          &lt;DiscreteObjectKeyFrame.Value&gt;
                                              &lt;BitmapImage UriSource="{Binding RelativeSource={RelativeSource TemplatedParent},Path=UnCheckedImagePath, Converter={StaticResource stringToImageConverter}}" /&gt;
                                          &lt;/DiscreteObjectKeyFrame.Value&gt;
                                      &lt;/DiscreteObjectKeyFrame&gt;
                                  &lt;/ObjectAnimationUsingKeyFrames&gt;
                              &lt;/Storyboard&gt;
                          &lt;/VisualState&gt;
                          &lt;VisualState x:Name="Indeterminate"/&gt;
                      &lt;/VisualStateGroup&gt;
                  &lt;/VisualStateManager.VisualStateGroups&gt;--&gt;
              &lt;/Image&gt;
  
          &lt;/ControlTemplate&gt;
  
  &lt;StackPanel x:Name="LayoutRoot" Background="{StaticResource PhoneForegroundBrush}" Orientation="Horizontal"&gt;
          &lt;Controls:ImageCheckbox CheckedImagePath="treble_checked.png" UnCheckedImagePath="treble_unchecked.png" Height="72" HorizontalAlignment="Left" VerticalAlignment="Top" Template="{StaticResource CheckboxImageTemplate}" Margin="0,0,10,0" &gt;
              &lt;Custom:Interaction.Triggers&gt;
                  &lt;Custom:EventTrigger EventName="Click"&gt;
                      &lt;GalaSoft_MvvmLight_Command:EventToCommand CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Command="{Binding TreblePressedCommand}"/&gt;
                  &lt;/Custom:EventTrigger&gt;
              &lt;/Custom:Interaction.Triggers&gt;
          &lt;/Controls:ImageCheckbox&gt;
  
      &lt;/StackPanel&gt;
  </code></pre>
  
  <p>I've tried to make it all work at first, but I don't seem to even get the first Source property of the image to load. The commented part (VisualStateManager states) doesn't work either, but i think it must be the same problem.. in this case I'd need a converter to return an Uri instead of a BitmapImage, because UriSource is of type Uri, and Source is of type Image.
  I'm getting errors in the converter, where I can't load the images (always falling into the image_imageFailed event). I've set the images as resources in the assembly... what am i doing wrong?? this is driving me crazy!!!!</p>
  
  <p>[EDIT] : I've tried doing as suggested, and changed the dependency property to Uri, but I can't get it to work
  If i say</p>
  
  <pre><code>&lt;Controls:ImageCheckbox CheckedImagePath="Images/treble_checked.png" UnCheckedImagePath="Images/treble_unchecked.png" Height="72" HorizontalAlignment="Left" VerticalAlignment="Top" Template="{StaticResource CheckboxImageTemplate}" Margin="0,0,10,0" &gt;
  </code></pre>
  
  <p>and in the template's VisualState :</p>
  
  <pre><code>&lt;BitmapImage UriSource="{Binding Path=UnCheckedImagePath, RelativeSource={RelativeSource TemplatedParent}}" /&gt;
  </code></pre>
  
  <p>it tells me that the xaml isn't valid and get an error. If i use TemplateBinding like this :</p>
  
  <pre><code>&lt;BitmapImage UriSource="{TemplateBinding UnCheckedImagePath}" /&gt;
  </code></pre>
  
  <p>it doesn't complain, but the image doesn't load (appear blank). I think i'm getting close, but still haven't found the solution...</p>
  
  <p>[EDIT 2] : last try...</p>
  
  <p>usage :</p>
  
  <pre><code>&lt;StackPanel x:Name="LayoutRoot" Background="{StaticResource PhoneForegroundBrush}" Orientation="Horizontal"&gt;
          &lt;Controls:ImageCheckbox Style="{StaticResource TheImageCheckboxStyle}" CheckedImagePath="Images/treble_checked.png" UnCheckedImagePath="Images/treble_unchecked.png" Height="72" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,0,10,0" &gt;
              &lt;Custom:Interaction.Triggers&gt;
                  &lt;Custom:EventTrigger EventName="Click"&gt;
                      &lt;GalaSoft_MvvmLight_Command:EventToCommand CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Command="{Binding TreblePressedCommand}"/&gt;
                  &lt;/Custom:EventTrigger&gt;
              &lt;/Custom:Interaction.Triggers&gt;
          &lt;/Controls:ImageCheckbox&gt;
  
      &lt;/StackPanel&gt;
  </code></pre>
  
  <p>style (trying to copy what you pasted and removing what i thought are unnecessary parts)</p>
  
  <pre><code>&lt;UserControl.Resources&gt;
  
          &lt;Style x:Key="TheImageCheckboxStyle" TargetType="Controls:ImageCheckbox"&gt;
              &lt;Setter Property="Template"&gt;
                  &lt;Setter.Value&gt;
                      &lt;ControlTemplate TargetType="CheckBox"&gt;
                          &lt;Grid Background="Transparent"&gt;
                              &lt;VisualStateManager.VisualStateGroups&gt;                                   
                                  &lt;VisualStateGroup x:Name="CheckStates"&gt;
                                      &lt;VisualState x:Name="Checked"&gt;
                                          &lt;Storyboard&gt;
                                              &lt;ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckMark"
                                                                             Storyboard.TargetProperty="Visibility"&gt;
                                                  &lt;DiscreteObjectKeyFrame KeyTime="0"&gt;
                                                      &lt;DiscreteObjectKeyFrame.Value&gt;
                                                          &lt;Visibility&gt;Visible&lt;/Visibility&gt;
                                                      &lt;/DiscreteObjectKeyFrame.Value&gt;
                                                  &lt;/DiscreteObjectKeyFrame&gt;
                                              &lt;/ObjectAnimationUsingKeyFrames&gt;
                                              &lt;ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckMark"
                                                                             Storyboard.TargetProperty="Source"&gt;
                                                  &lt;!--  Magic!  --&gt;
                                                  &lt;DiscreteObjectKeyFrame KeyTime="0"
                                                                          Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CheckedImagePath}" /&gt;
                                              &lt;/ObjectAnimationUsingKeyFrames&gt;
                                          &lt;/Storyboard&gt;
                                      &lt;/VisualState&gt;
                                      &lt;VisualState x:Name="Unchecked"&gt;
                                          &lt;Storyboard&gt;
                                              &lt;ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckMark"
                                                                             Storyboard.TargetProperty="Visibility"&gt;
                                                  &lt;DiscreteObjectKeyFrame KeyTime="0"&gt;
                                                      &lt;DiscreteObjectKeyFrame.Value&gt;
                                                          &lt;Visibility&gt;Visible&lt;/Visibility&gt;
                                                      &lt;/DiscreteObjectKeyFrame.Value&gt;
                                                  &lt;/DiscreteObjectKeyFrame&gt;
                                              &lt;/ObjectAnimationUsingKeyFrames&gt;
                                              &lt;ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckMark"
                                                                             Storyboard.TargetProperty="Source"&gt;
                                                  &lt;!--  Magic!  --&gt;
                                                  &lt;DiscreteObjectKeyFrame KeyTime="0"
                                                                          Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=UnCheckedImagePath}" /&gt;
                                              &lt;/ObjectAnimationUsingKeyFrames&gt;
                                          &lt;/Storyboard&gt;
                                      &lt;/VisualState&gt;
                                  &lt;/VisualStateGroup&gt;
                              &lt;/VisualStateManager.VisualStateGroups&gt;
                              &lt;Grid Margin="{StaticResource PhoneTouchTargetLargeOverhang}"&gt;
                                  &lt;Grid.ColumnDefinitions&gt;
                                      &lt;ColumnDefinition Width="32" /&gt;
                                      &lt;ColumnDefinition Width="*" /&gt;
                                  &lt;/Grid.ColumnDefinitions&gt;
                                  &lt;Border x:Name="CheckBackground"
                                          Width="32"
                                          Height="32"
                                          HorizontalAlignment="Left"
                                          VerticalAlignment="Center"
                                          Background="{TemplateBinding Background}"
                                          BorderBrush="{TemplateBinding Background}"
                                          BorderThickness="{StaticResource PhoneBorderThickness}"
                                          IsHitTestVisible="False" /&gt;
                                  &lt;Rectangle x:Name="IndeterminateMark"
                                             Grid.Row="0"
                                             Width="16"
                                             Height="16"
                                             HorizontalAlignment="Center"
                                             VerticalAlignment="Center"
                                             Fill="{StaticResource PhoneRadioCheckBoxCheckBrush}"
                                             IsHitTestVisible="False"
                                             Visibility="Collapsed" /&gt;
                                  &lt;!--  Magic! Default to UnCheckedImagePath  --&gt;
                                  &lt;Image x:Name="CheckMark"
                                         Width="24"
                                         Height="18"
                                         HorizontalAlignment="Center"
                                         VerticalAlignment="Center"
                                         IsHitTestVisible="False"
                                         Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=UnCheckedImagePath}"
                                         Stretch="Fill"
                                         Visibility="Collapsed" /&gt;
                                  &lt;ContentControl x:Name="ContentContainer"
                                                  Grid.Column="1"
                                                  Margin="12,0,0,0"
                                                  Content="{TemplateBinding Content}"
                                                  ContentTemplate="{TemplateBinding ContentTemplate}"
                                                  Foreground="{TemplateBinding Foreground}"
                                                  HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  Padding="{TemplateBinding Padding}"
                                                  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" /&gt;
                              &lt;/Grid&gt;
                          &lt;/Grid&gt;
                      &lt;/ControlTemplate&gt;
                  &lt;/Setter.Value&gt;
              &lt;/Setter&gt;
  
          &lt;/Style&gt;
  </code></pre>