title: MVVM: Two-Way Binding To Array In The Model (w/o INotifyPropertyChanged)
body: <p>Let's say my Model has a property that's an array of primitives:</p>
  
  <pre><code>class Model
  {
      public static int MaxValue { get { return 10; } }
  
      private int[] _array = {1,2,3,4};
      public int[] MyArray
      {
         get
         { 
            return _array; 
         }
         set
         {
             for (int i = 0; i &lt; Math.Min(value.Length, _array.Length); i++)
                 _array[i] = Math.Min(MaxValue, value[i]);
         }
  }
  </code></pre>
  
  <p>The ViewModel then wraps this property this for consumption by the View:</p>
  
  <pre><code>class ViewModel
  {
      Model _model = new Model();
      public int[] MyArray
      {
          get { return _model.MyArray; }
          set { _model.MyArray = value; }
      }
  }
  </code></pre>
  
  <p>And finally, I present an ItemsControl so the user can set each value with a Slider:</p>
  
  <pre><code>&lt;ItemsControl ItemsSource="{Binding MyArray}" &gt;
    &lt;ItemsControl.ItemTemplate&gt;
      &lt;DataTemplate&gt;
        &lt;Slider Value="{Binding Path=., Mode=TwoWay}" Minimum="0" Maximum="{Binding Source={x:Static Model.MaxValue}, Mode=OneWay}" /&gt;
      &lt;/DataTemplate&gt;
    &lt;/ItemsControl.ItemTemplate&gt;
  &lt;/ItemsControl&gt;
  </code></pre>
  
  <p>In this simple example, TwoWay binding won't work - the slider doesn't update the properties.  This is solved by wrapping each array element in an object, like:</p>
  
  <pre><code>class Wrap
  {
      public int Value{ get; set; }
  }
  </code></pre>
  
  <p>The MyArray properties then become a Wrap[], and we bind to Path=Value.  While it does feel a little "messy" to wrap arrays in the Model this way (note: the model is also used by other WinForms applications), it does solve the problem and the sliders can now update the array.</p>
  
  <p>Next, let's add a button to reset the array values.  When clicked:</p>
  
  <pre><code>for( int i = 0; i &lt; MyArray.Length; i++ )
      MyArray[i].Value = i;
  </code></pre>
  
  <p>Another problem has arisen: after clicking the button, the sliders don't reflect the new values.  This can be solved by changing the array to an ObservableCollection, and updating the values with object replacement:</p>
  
  <pre><code>   //MyArray is now ObservableCollection&lt;Wrap&gt;
     for( int i = 0; i &lt; MyArray.Count; i++ )
          MyArray[i] = new Wrap() { Value = i };
  </code></pre>
  
  <p><strong>First question:</strong> My understanding is that in MVVM, the Model classes aren't supposed to have anything to do with notification - that should be handled entirely by the VM.  Usually such discussion surrounds INotifyPropertyChanged, but it seems to me like changing arrays to ObservableCollection is really starting to muck up the Model for the sake of...well...notification.  Would this not be considered bad practice?  All the other (WinForms) apps that use the Model will now have to be updated to understand this wacky collection-of-objects-wrapping-primitives, just to make it work with databinding.  Is there perhaps some other way around this?</p>
  
  <p><strong>Second Question</strong>: My real issue comes from one more requirement.  In the ViewModel, the array values (and other properties) are actually used to generate an image - and every time a property is updated, the image needs to be refreshed.  For my other (non-array) properties, I do:</p>
  
  <pre><code>class ViewModel
  {
      public int SomeProperty
      {
        get { return _model.SomeProperty; }
        set { _model.SomeProperty = value; RefreshImage(); }
      }
  }
  </code></pre>
  
  <p>But I can't figure out how to update the image in the case of changing MyArray values.  I've tried subscribing to the ObservableCollection's CollectionChanged event, but it only gets triggered by the button click (object replacement), not by the sliders (as they update the Value within the object within the collection).  I could make the Wrap objects INotifyPropertyChanged and subscribe to ObservableCollection.PropertyChanged...but then I'm sending off notifications from within the model, which (according to everything I've ever read) you're not supposed to do in MVVM.  So I'm stuck either unable to refresh the image when the user manipulates the sliders, or having to basically break MVVM - with INotifyPropertyChanged, ObservableCollections, and wrappers all in my Model.  Surely there must be a cleaner way to go about this...?</p>