title: MVVM IValueConverter Convert method getting empty string argument when expecting a float
body: <p>This may get a tad long, but here goes.  I have created a small, wizard-style sample app using the MVVM pattern (basically a dumbed-down version of the code in my "real" app).  In this app, the main window moves from through a List&lt;..> of view models, with each view model displaying its associated view.  I have 2 view model classes that are essentially identical, and they display the same view.</p>
  
  <p>On the view is a combo box, populated with an array of float.  The SelectedItem is bound to a float property on the view model.  I have created a template for the combo box to display each item as a TextBlock, with the text taking the float value and going through a value converter.</p>
  
  <p>The problem, when I switch back and forth between view models, all works fine as long as every view model I switch to is of the same class.  As soon as I change the current page to an instance of a different view model, the value converter's Convert gets called with a 'value' parameter that is a zero-length string.  Up til then, Convert was only being called with a float, as I would expect.</p>
  
  <p>My question : why is the converter being called with the empty string ONLY in the case of switching view model classes?  </p>
  
  <p>I am attaching the main window XAML and view model, as well as the view/view models displayed for each "page".  You'll notice that the main window view model has a list containing 2 instances of PageViewModel and 2 instances of OtherViewModel.  I can switch back and forth between the first 2 fine, and the value converter only gets called with a float value.  Once I switch to the first OtherViewModel instance, the converter gets an "extra" call with an empty string as the value.</p>
  
  <p>Code snippets :</p>
  
  <ol>
  <li><p>MainWindow</p>
  
  <pre><code>&lt;Grid.Resources&gt;
      &lt;DataTemplate DataType="{x:Type local:PageViewModel}"&gt;
          &lt;local:PageView /&gt;
      &lt;/DataTemplate&gt;
      &lt;DataTemplate DataType="{x:Type local:OtherViewModel}"&gt;
          &lt;local:PageView /&gt;
      &lt;/DataTemplate&gt;
  &lt;/Grid.Resources&gt;
  
  &lt;!-- Page --&gt;
  &lt;ContentControl Margin="5,5,5,35"
                  Height="100"
                  IsTabStop="False"
                  Content="{Binding CurrentPage}" /&gt;
  
  &lt;!-- Commands --&gt;
  &lt;Button Margin="5,115,0,0" 
          Width="75"
          Content="&amp;lt; Back"
          VerticalAlignment="Top"
          HorizontalAlignment="Left"
          Command="{Binding BackCommand}" /&gt;
  
  &lt;Button Margin="85,115,0,0"
          Width="75"
          Content="Next &amp;gt;"
          VerticalAlignment="Top"
          HorizontalAlignment="Left"
          Command="{Binding NextCommand}" /&gt;
  </code></pre></li>
  <li><p>MainWindowViewModel</p>
  
  <pre><code>    public MainWindowViewModel()
      {
         m_pages = new List&lt;BaseViewModel&gt;();
         m_pages.Add(new PageViewModel(1, 7f));
         m_pages.Add(new PageViewModel(2, 8.5f));
         m_pages.Add(new OtherViewModel(3, 10f));
         m_pages.Add(new OtherViewModel(4, 11.5f));
         m_currentPage = m_pages.First();
  
         m_nextCommand = new BaseCommand(param =&gt; this.OnNext(), param =&gt; this.EnableNext());
         m_backCommand = new BaseCommand(param =&gt; this.OnBack(), param =&gt; this.EnableBack());
      }
  
      // Title
  
      public string Title
      {
         get
         {
            return (CurrentPage != null) ? CurrentPage.Name : Name;
         }
      }
  
      // Pages
  
      BaseViewModel m_currentPage = null;
      List&lt;BaseViewModel&gt; m_pages = null;
  
      public BaseViewModel CurrentPage
      {
         get
         {
            return m_currentPage;
         }
         set
         {
            if (value == m_currentPage)
               return;
            m_currentPage = value;
            OnPropertyChanged("Title");
            OnPropertyChanged("CurrentPage");
         }
      }
  
      // Back
  
      ICommand m_backCommand = null;
      public ICommand BackCommand
      {
         get
         {
            return m_backCommand;
         }
      }
      public void OnBack()
      {
         CurrentPage = m_pages[m_pages.IndexOf(CurrentPage) - 1];
      }
      public bool EnableBack()
      {
         return CurrentPage != m_pages.First();
      }
  
      // Next
  
      ICommand m_nextCommand = null;
      public ICommand NextCommand
      {
         get
         {
            return m_nextCommand;
         }
      }
      public void OnNext()
      {
         CurrentPage = m_pages[m_pages.IndexOf(CurrentPage) + 1];
      }
      public bool EnableNext()
      {
         return CurrentPage != m_pages.Last();
      }
   }
  </code></pre></li>
  </ol>
  
  <p>Notice the 2 instance of one view model followed by 2 instances of the other.</p>
  
  <ol>
  <li><p>PageView</p>
  
  <pre><code>&lt;Grid.Resources&gt;
      &lt;x:Array x:Key="DepthList"
               Type="sys:Single"&gt;
          &lt;sys:Single&gt;7&lt;/sys:Single&gt;
          &lt;sys:Single&gt;8.5&lt;/sys:Single&gt;
          &lt;sys:Single&gt;10&lt;/sys:Single&gt;
          &lt;sys:Single&gt;11.5&lt;/sys:Single&gt;
      &lt;/x:Array&gt;
      &lt;local:MyConverter x:Key="MyConverter" /&gt;
  &lt;/Grid.Resources&gt;
  
  &lt;TextBlock Text="Values:"
             Margin="5,5,0,0"&gt;
  &lt;/TextBlock&gt;
  
  &lt;ComboBox Width="100"
            Height="23"
            VerticalAlignment="Top"
            HorizontalAlignment="Left"
            Margin="5,25,0,0"
            DataContext="{Binding}"
            SelectedItem="{Binding Depth}"
            ItemsSource="{Binding Source={StaticResource DepthList}}"&gt;
      &lt;ComboBox.ItemTemplate&gt;
          &lt;DataTemplate&gt;
              &lt;TextBlock Text="{Binding Converter={StaticResource MyConverter}}" /&gt;
          &lt;/DataTemplate&gt;
      &lt;/ComboBox.ItemTemplate&gt;
  &lt;/ComboBox&gt;
  </code></pre></li>
  <li><p>PageViewModel/OtherViewModel/MyConverter</p>
  
  <pre><code>   public class PageViewModel : BaseViewModel
     {
        public PageViewModel(int index, float depth)
        {
           Depth = depth;
           Name = "Page #" + index.ToString();
        }
  
        public float Depth
        {
           get;
           set;
        }
     }
  
     public class OtherViewModel : BaseViewModel
     {
        public OtherViewModel(int index, float depth)
        {
           Depth = depth;
           Name = "Other #" + index.ToString();
        }
  
        public float Depth
        {
           get;
           set;
        }
     }
  
     [ValueConversion(typeof(DateTime), typeof(String))]
     public class MyConverter : IValueConverter
     {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
           Debug.WriteLine("IValueConverter.Convert : received a " + value.GetType().Name);
  
           string text = "";
           if (value is float)
           {
              text = value.ToString();
           }
           else
           {
              throw new ArgumentException("MyConverter : input value is NOT a float.");
           }
  
           return text;
        }
  
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
           return float.Parse(value as string);
        }
     }
  </code></pre></li>
  </ol>
  
  <p>Note: I can remove the exception in the Convert method, and everything seems to work fine.  But, I would like to know why this is happening.  Why is the converter getting an empty string instead of the expected float, and only when we switch view models?</p>
  
  <p>Any insights would be greatly appreciated.  Thanks in advance...
  Joe</p>