Friday, August 27, 2010

Converters does not live well with Data Validation

If you throw an exception in a IValueConverter, then it will be propagated to UI, instead of caught by Data Validation code (Set ValidateOnException=True). Basically you have no way around this. So the only other choice is to add data annotations and do the validation there as suggested in this discussion.
// Confine value between 0 and 1

// type conversion error will be thrown as well

[Range(0,1)]
public int IntValue
{
get { return _intvalue; }
set
{
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = "IntValue" });
_intvalue = value;
}
}


There is another article that describes it better, even though the title says "Silverlight 4 vs Flex 4: Data Validation". (I actually clicked this link while researching this problem, but did not read it until I figured out the problem, and that's after a long time. :()

Xaml has a "Shadows" problem

If you declare a property "Shadows" (in VB terms) another property in its superclass, then Xaml loader will throw out an AmbiguousMatchException because it can not decide which one to use in this case, as a reflection operation will return multiple properties. Solution is to make the property Overridable (or virtual in C#) and overrides it.
The frustrating thing is: Despite the straight forward explanation that you have here, the debugging of this problem takes forever. There are two reasons for it:
1) AmbiguousMatchException does not tell you the offending property name and object it is raising against.
2) Microsoft Symbol Server, which supposedly should give you the source code for mscorlib, only turns out names of the method. No source code, and in turn the call parameters, are provided so there is virtually no way to find out what is wrong unless you have the knowledge and patience to go through the disassembly.
What I did ultimately is very much akin to the S&L (Save and Load) in games. I commented some code and see if the exception is raised. If not, I uncomment some. Until I found out the offending piece of code and discovered this little problem. Which is, by the way, not surprising at all. But it sure made my life miserable in the past 12 hours.

Tuesday, August 24, 2010

Copy Constructor, Clone and Polymorphism

This is an artsy name for a blog. But I think it sums up the puzzle I faced when I try to do deep copy. We will need a Copy Constructor and a Clone (or Copy) method that is polymorphed (virtual) to make deep copy work under polymorphism situations.
Imagine that: You need a deep copy mechanism, and you have an class hierarchy to do the copy. When you do copies, you may get a reference to one of the high level classes. But obviously you need to copy the entire object. So you need to have:
1. A copy constructor on every class.
2. A polymorphed Clone (or Copy) method on every class.
The Clone method should call the copy constructor and the copy constructor will in turn call its parent's copy constructor so all properties are deep copied.

Be careful of MemberwiseClone

If you have noticed, there is a protected method, MemberwiseClone, on Object. It is tempting to use it as it provides a quick way to do shallow copy, which is quite useful sometimes. But I fell into a trap yesterday and finally figured out the root during my walk today. :)
The problem comes from a combination of two factors:
1) MemberwiseClone: I am using it as a cheap way to copy Drag and Dropped content.
2) Parent property: One of the property of all Expression objects that I can copy, is the Parent property that points back to the containing object. This is because of the necessacity to quickly, and reliabilty, find out the parent for certain actions. These actions include Insert an Expression before another, and find out what is the Operator of the Logical expression to display a little "And" or "Or" before the sub expressions.
Long stories short: I drag and dropped a Binary expression "(a+b)" with the "b" being an EmptyExpression. Everything is fine, it seems. But when I drop a second Binary that is the same, problem shows. Because I did a MemberwiseClone on the first Binary, the "b" component of the first is pointing back at the "original" Binary, which is conveniently thrown away at this point. Now when the second Binary is dropped into the "b". "b" went back to the Parent, in this case thrown away, to update its property. Because the thrown away Parent is not show on the UI, it seems nothing is changed. Surprise!
But the worse things comes after: When the old Parent is updating, it dutifully put the "b"'s Parent to nothing, as it is useless now. If I drop another Expression into "b" (which is still shown on the screen), its Parent is empty, and crash happens when it tries to ask its parent to replace itself with the dropped Expression.
This is a twisted explaination. Hopefully I have sometime to draw a Visio to showcase the problem.

Monday, August 23, 2010

Fully Qualified Type Name in Silverlight

You can ignore the Culture and PublicKey, and they will be defaulted to "neutral" and "null" respectively. However, you must have the following three components in order for Type.GetType(typename) to return you the correct type (otherwise, you will get a Null/Nothing, which is very frustrating).
1. FullName (Namespace + Class name, etc. Complicated when it is a nested class, or generic class, etc.)
2. Assembly
3. Version
An example is:
"DMS.RuleEditor.ViewModel.Logical, RuleEditorViewModel, Version=1.0.0.0"

Find out position of an UIElement in Silverlight

Use GeneralTransform to get the position of the UI Element:

1 GeneralTransform objGeneralTransform = myObj.TransformToVisual(Application.Current.RootVisual as UIElement);
2 Point point = objGeneralTransform.Transform(new Point(0, 0));
3 double myObjTop = point.Y;
4 double myObjLeft = point.X;

Monday, August 2, 2010

Generic.xaml in Silverlight 4

After much pain and suffering, :), I found that the Generic.xaml has to be put under Themes folder for it to work in Silverlight 4. It makes sense... but the postings on the internet are not helping. Some say it must be under the root folder, and others only addressing WPF. Am I the only person trying to do a custom control in SL4?