Несколько экземпляров пользовательского элемента управления с холстом вызывают исключение в Silverlight - PullRequest
3 голосов
/ 17 июля 2010

У меня есть пользовательский элемент управления, в котором есть сетка (та, которую вы получаете автоматически при создании пользовательского элемента управления) и холст внутри нее.

<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 и добавляет его к ControlOne, прежде чем пытаться добавить это к ControlTwo. Это приводит к исключению, потому что вы не можете иметь элемент, связанный с двумя элементами управления одновременно.

Я предполагаю, что это как-то связано с тем, что холст в каждом экземпляре имеет одно и то же имя, поэтому, когда он разрешает "SurfaceCanvas", он возвращает два экземпляра назад и добавляет к каждому по порядку. Это всего лишь предположение, основанное на наблюдении.

Что я делаю не так?

1 Ответ

3 голосов
/ 17 июля 2010

Мне потребовалась минута, но это сложно:

У вас есть значение по умолчанию для вашего DependencyProperty. Значение по умолчанию создается только один раз для вашего DependencyProperty, а затем присваивается обоим экземплярам вашего TestControl. Таким образом, когда вы добавляете что-то в TestControl.Items, вы добавляете это в общую коллекцию ObservbleCollection, которая теперь имеет два делегата события CollectionChanged, каждый из которых добавляет новые элементы в соответствующий Canvas.

Удалить значение по умолчанию ItemsProperty. Либо создайте ObservbleCollection в конструкторе, либо интерпретатор xaml создаст его для каждого TestControl.

Правило: используйте значение по умолчанию для DependencyProperty только с типами значений, а не со ссылочными типами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...