Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
ValueConverter behaviour
Message
From
15/07/2011 14:23:43
 
 
To
15/07/2011 12:25:56
General information
Forum:
ASP.NET
Category:
Windows Presentation Foundation (WPF)
Environment versions
Environment:
C# 4.0
Miscellaneous
Thread ID:
01518156
Message ID:
01518271
Views:
26
>>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.
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform