本文將簡單分析幾個Silverlight程序開發中經常遇到的問題的解決方案。
1.Element is already the child of another element
從字面意思,可以理解爲:元素已經是另一個元素的子元素。在Silverlight中,每一個Element均只能從屬於一個父元素;如果重複將一個元素分配給不同的父元素則會出現這樣的異常。
這種錯誤多在通過代碼添加子元素等情況中出現,而且對於初學者甚至很難想明白爲什麼會出錯,比如在我上一篇文章中提到的動畫:
每一個動畫的TimeLine都通過關鍵幀動畫來實現,其中有一段代碼爲:
DoubleAnimationUsingKeyFrames xTimeLine = new DoubleAnimationUsingKeyFrames();
var xKeyFrames = xTimeLine.KeyFrames;
xKeyFrames.Add(this.GetKeyFrame(0, 0));
xKeyFrames.Add(this.GetKeyFrame(2.5, 30));
xKeyFrames.Add(this.GetKeyFrame(5.0, 90));
如果將這段代碼修改爲:
DoubleAnimationUsingKeyFrames xTimeLine = new DoubleAnimationUsingKeyFrames();
var xKeyFrames = new DoubleKeyFrameCollection();
xKeyFrames.Add(this.GetKeyFrame(0, 0));
xKeyFrames.Add(this.GetKeyFrame(2.5, 30));
xKeyFrames.Add(this.GetKeyFrame(5.0, 90));
foreach (var frame in xKeyFrames)
{
xTimeLine.KeyFrames.Add(frame);
}
則會在 xTimeLine.KeyFrames.Add(frame);行拋出這樣的異常:Element is already the child of another element。
這段代碼,在我們的以往經驗中,大家可能不會覺得有什麼問題,而這裏之所以會出現異常的原因則是因爲DoubleKeyFrameCollection不是一個單純的集合了,它不僅實現了集合的一些接口,還繼承於DependencyObject,當我們向其中添加DoubleKeyFrame(也屬於DependencyObject的後代)的時候,實際上也將其parent設置爲了這個集合對象;於是當我們再試圖將其添加到其他元素子元素中時,就拋出了異常。
2.Cannot resolve TargetProperty
這類異常的拋出往往是因爲我們沒有設置相應的Proerty:在XAML中即爲沒有添加相應的屬性元素,在CODE中即爲沒有對相應的屬性實例化。
比如如果去掉前一篇文章中的ball.RenderTransform = new CompositeTransform();這行代碼;則會在Storyboard.SetTargetProperty(xTimeLine, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)"));拋出這樣的異常:Cannot resolve TargetProperty (UIElement.RenderTransform).(CompositeTransform.TranslateY) on specified object.
解決方法就是實例化RenderTransform這個屬性:ball.RenderTransform = new CompositeTransform();
如果是使用XAML中的Stroryboard拋出了這個異常,那麼相應的解決方案即爲添加相應的元素,比如上面CODE的等價XAML是:
<Canvas.RenderTransform>
<CompositeTransform/>
</Canvas.RenderTransform>
注意:需要將Canvas修改爲你設置動畫的Element類型。
3.與WPF的區別
Silverlight的“值域”與“定義域”均小於WPF,因此在WPF中有的功能與特性,在Silverlight中並不一定有,比如DoubleAnimationUsingPath在Silverlight並無與之對應的類。我們在開發的時候一定要清楚不同框架之間的區別與聯繫,這樣纔可能儘量避免不必要的錯誤出現。