>>Hi,
>>Background:
>>I have data stored in a SQL table as varbinary(max) (which in .NET is byte[]). The data is a serialized copy of a WPF Framework Element. I'm trying to decide where, in a MVVM model, this deserialization should take place. One possibility would be to just use a ValueConverter so the conversion happens between the VM and the View so I came up with this:
public class IllObjectBinding : Binding
>> {
>> public IllObjectBinding()
>> {
>> Converter = new IllObjectValueConverter();
>> }
>>
>> [ValueConversion(typeof(byte[]), typeof(ILLObject))]
>> class IllObjectValueConverter : IValueConverter
>> {
>>
>> public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
>> {
>> if (value == null) return Binding.DoNothing;
>> //Change from bytearray to object instance
>> byte[] b = (byte[])value;
>> return (ILLObject)BinarySerializer.Deserialize(b);
>> }
>>
>> public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
>> {
>> ILLObject o = (ILLObject)value;
>> return (byte[]) BinarySerializer.SerializeToByteArray(o);
>> }
>> }
>> }
(I thought I'd embed the actual converter within the binding so that the UI guys don't have to remember to use it...)
>>
>>Now when the Target changes then ConvertBack() gets called as expected. But what surprised me is that the Convert() is also immediately called even though I'm not raising a PropertyChanged on the VM. Looking at the stack trace it seems as if this is being called internally by the Binding itself (Data.BindingExpression.TransferValue()) . Can't find anything in the documentation that would indicate this is normal behaviour but obviously in my scenario it is not desirable (BinarySerializer.Deserialize is not exactly a light weight conversion and, in this case, is unneccessary).
>>I've verified that the same thing happens with a simple, bog-standard ValueConverter - anyone know why? Or how it can be supressed? (I could set a flag in ConvertBack() so that the next Convert would do nothing but it seems a bit risky.....)
>>
>>It would probably be a better idea to add a property to the VM and not use a ValueConverter at all so it's no big deal - just curious as to why Binding/ValueConverter is implemented this way.....
>
>I think I've seen that, but the converter was light weight so it wasn't an issue. Not sure why they decided to call convert, but I think PropertyChanged is ignored when a binding is updating it's source. So it may be to ensure the items are in sync.
Thinking about this - given that more than one target can be attached to the same binding then I thought having the Convert fire automatically might quarantee that the other targets were automatically updated. But it appears that this is not the case - after the Convert() the ConvertBack() only fires for the target that triggered the change so I guess that is BindingExpression related. To get all targets to update you still have to raise the PropertyChanged event from the source property Setter.
I've experimented with setting a flag in the ConvertBack() then checking and resetting it in the Convert(). This works in the simple case but I worry that there might be possible side effects.....
>
>I did find this:
>
>
http://social.msdn.microsoft.com/Forums/en/wpf/thread/b9a7cb6a-0bd3-4865-bb85-87beeb7062e8>
>It's the opposite of your problem, but it sounds like the behavior may be related to the UpdateSourceTrigger setting. However... that may not be much help.
Not a help (:-{ ) but it raises another issue. If I need to change the source value programmatically (OK I suppose I shouldn't need to do that in a strict MVVM scenario but..) then the UpdateSourceTrigger needs to be 'PropertyChanged'. But if that has to be set on, for example, a TextBox then I'm stuck with the associated behaviour of having the ConvertBack() fire for every keystroke. Fair enough, I suppose, - you can't have it both ways :-{
>Since your basically storing a view in your model. I think deserializing in the VM would be acceptable.
I'm leaning more that way. If the FrameworkElement exists in deserialized form in the VM then I have the option of manipulating properties directly in the VM. Don't see a need for that at the moment (and it may not be a good thing) - guess I need to dwell on this a bit more.