我有一個用戶控件,它具有一個網格(您在創建用戶控件時自動獲取的網格)和一個畫布。用畫布控制用戶的多個實例在Silverlight中導致異常
<Grid x:Name="LayoutRoot" Background="White">
<Canvas x:Name="SurfaceCanvas">
</Canvas>
</Grid>
在CS文件中,我定義了一個「Items」集合。
public ObservableCollection<TestItem> Items {
get { return (ObservableCollection<TestItem>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(ObservableCollection<TestItem>),
typeof(TestControl),
new PropertyMetadata(new ObservableCollection<TestItem>()));
的TestItem類聲明:
public class TestItem : ContentControl { ... }
項目通過XAML添加到它。
<my:TestControl x:Name="ControlOne" Height="100" Width="100">
<my:TestControl.Items>
<my:TestItem x:Name="ItemOne">One</my:TestItem>
</my:TestControl.Items>
</my:TestControl>
<my:TestControl x:Name="ControlTwo" Height="100" Width="100">
<my:TestControl.Items>
<my:TestItem x:Name="ItemTwo">Two</my:TestItem>
</my:TestControl.Items>
</my:TestControl>
將項目添加到集合時,我將它們添加到畫布。
void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
switch(e.Action) {
case NotifyCollectionChangedAction.Add:
foreach(Control item in e.NewItems) {
SurfaceCanvas.Children.Add(item);
}
break;
}
}
現在,問題所在。
如果有這個控件的一個實例,一切都很好。但是,當我定義第二個實例時,我會收到一個InvalidOperationException
:「元素已經是另一個元素的子元素」,該元素添加到ControlTwo
。
當我步,看着元素被添加到畫布上,什麼情況是,它創造ItemOne
,並將其添加到ControlOne
,然後創建ItemTwo
,並試圖將其添加到ControlTwo
之前將其添加到ControlOne
。這會導致異常,因爲您無法一次將父元素設爲父元素。
我的猜測是它與每個實例中的畫布具有相同名稱的事實有關,所以當它解析「SurfaceCanvas」時,它將返回兩個實例並按順序添加到每個實例中。這只是基於觀察的猜測。
我在做什麼錯?
謝謝你一步一步推動我的教育。 – redman 2010-07-17 14:58:24
+1,這是所有具有引用類型的DependencyProperties的經典陷阱。不過,我會稍微放鬆一下規則,「僅對值類型使用默認值__或___以引用不可變對象」。一個「不可變」的好例子就是一個「字符串」。 – AnthonyWJones 2010-07-17 18:29:20