Ошибка "Указанный элемент уже является логическим дочерним элементом другого элемента"?

У меня есть TabControl, и каждая вкладка может содержать один и тот же интерфейс, но с разными данными. На любой вкладке пользователь может нажать на кнопку и открыть всплывающее окно. Это задает свойство Style для ViewModel, указывающее, какой стиль использовать для всплывающего интерфейса. Стиль привязан к настраиваемому DependecyProperty, который привязан к пользовательскому PopupUserControl. Моя проблема в том, что когда вторая копия всплывающего окна открывается на другой вкладке, я получаю следующую ошибку (независимо от того, какой стиль применяется):

Указанный элемент уже логический дочерний элемент другого элемента. Сначала отключите его.

Команда ButtonClick:

MyViewModel vm = ((Button)sender).DataContext as MyViewModel;
if (vm != null)
{
    Style popupStyle = (Style)Application.Current.FindResource("SomePopupStyle");
    vm.EditPanelStyle= popupStyle ;
}

Это вызывает событие PropertyChange в стиле

public Style EditPanelStyle
{
    get { return _editPanelStyle; }
    set
    {
        if (_editPanelStyle != value)
        {
            _editPanelStyle = value;
            OnPropertyChanged("EditPanelStyle");
        }
    }
}

Что вызывает событие OnPropertyChanged в ViewModelBase

protected virtual void OnPropertyChanged(string propertyName)
{
    this.VerifyPropertyName(propertyName);

    PropertyChangedEventHandler handler = this.PropertyChanged;
    if (handler != null)
    {
        var e = new PropertyChangedEventArgs(propertyName);
        handler(this, e);
    }
}

Ошибка возникает в строке handler(this, e); в ViewModelBase

ИЗМЕНИТЬ

TabItem содержит холст и группу панелей, которые можно добавлять/удалять/перемещать/и т.д. Каждая панель имеет свой собственный каталог ресурсов. Изнутри Panel я могу установить PopupStyle просто отлично, и он применяется без проблем. Стиль, используемый в панелях, также определяется в PanelResourceDictionary.

Основное отличие от того, что происходит, и того, что преуспевает, - стиль находится в разных местах.

РЕДАКТИРОВАТЬ # 2 Стиль, который терпит неудачу - LookupDialog - это пользовательский пользовательский элемент управления WPF

<!-- Popup Style for LookupDialog -->
<Style x:Key="LookupDialogBaseStyle" TargetType="{x:Type localControls:DraggablePanel}" BasedOn="{StaticResource GenericPopupStyle}">
    <Setter Property="Canvas.Left" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type localControls:PopupPanel}}, 
        Path=ActualWidth, Converter={StaticResource PercentToDoubleConverter}, ConverterParameter=.25}" />
    <Setter Property="Canvas.Top" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type localControls:PopupPanel}}, 
        Path=ActualHeight, Converter={StaticResource PercentToDoubleConverter}, ConverterParameter=.3}" />
    <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type localControls:PopupPanel}}, 
        Path=ActualWidth, Converter={StaticResource PercentToDoubleConverter}, ConverterParameter=.5}" />
    <Setter Property="Height" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type localControls:PopupPanel}}, 
        Path=ActualHeight, Converter={StaticResource PercentToDoubleConverter}, ConverterParameter=.4}" />

    <!--<Setter Property="localControls:PopupPanel.PopupEnterKeyCommand" Value="{Binding Path=SaveCommand}" />-->
    <Setter Property="localControls:PopupPanel.PopupEscapeKeyCommand" Value="{Binding Path=CancelCommand}" />

    <Setter Property="Header" Value="{Binding Path=Header}" />
    <Setter Property="localControls:PopupPanel.BackgroundOpacity" Value="0" />

    <Setter Property="Content">
        <Setter.Value>
            <localControls:LookupDialog 
                DataContext="{Binding}"
                BorderBrush="{StaticResource DarkColor}" />
        </Setter.Value>
    </Setter>
</Style>

<!-- Base Style for a Popup (DraggablePanel) -->
<Style x:Key="GenericPopupStyle" TargetType="{x:Type localControls:DraggablePanel}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type localControls:DraggablePanel}">
                <Border Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">
                    <DockPanel>
                        <!-- Header -->
                        <Border 
                            DockPanel.Dock="Top"
                            MinHeight="20"
                            Background="{DynamicResource TabItem_BackgroundBrush_Unselected}"
                            BorderBrush="{StaticResource DarkColor}"
                            BorderThickness="1"
                            CornerRadius="5,5,0,0"
                            Padding="2,3,2,2"
                            SnapsToDevicePixels="True"
                            >

                            <ContentPresenter x:Name="PART_DraggablePanelHeader" ContentSource="Header" />
                        </Border>

                        <!-- Content -->
                        <Border Background="{StaticResource DefaultBackground}" 
                                BorderBrush="{StaticResource DarkColor}" 
                                BorderThickness="1,0,1,1"
                                SnapsToDevicePixels="True">
                            <ContentPresenter ContentSource="Content" />
                        </Border>
                    </DockPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Стиль, который работает:

<!-- Example Popup Style for a Panel -->
<Style x:Key="AgentDesktop_NotesPanelPopupStyle" TargetType="{x:Type ContentControl}">
    <Setter Property="Canvas.Left" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type localControls:PopupPanel}}, 
        Path=ActualWidth, Converter={StaticResource PercentToDoubleConverter}, ConverterParameter=.2}" />
    <Setter Property="Canvas.Top" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type localControls:PopupPanel}}, 
        Path=ActualHeight, Converter={StaticResource PercentToDoubleConverter}, ConverterParameter=.32}" />
    <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type localControls:PopupPanel}}, 
        Path=ActualWidth, Converter={StaticResource PercentToDoubleConverter}, ConverterParameter=.6}" />
    <Setter Property="Height" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type localControls:PopupPanel}}, 
        Path=ActualHeight, Converter={StaticResource PercentToDoubleConverter}, ConverterParameter=.36}" />

    <Setter Property="localControls:PopupPanel.PopupEnterKeyCommand" Value="{Binding Path=SaveCommand}" />
    <Setter Property="localControls:PopupPanel.PopupEscapeKeyCommand" Value="{Binding Path=HidePopupCommand}" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <!-- Control Template removed to make this easier to read, but it created from standard WPF controls with nothing special -->
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Ответы

Ответ 1

Моя проблема заключалась в том, что я устанавливал Content в моем стиле, а Content не может иметь более одного логического родителя. Мне нужно было переместить это вместо Template. Поскольку я не хотел потерять базовый стиль, я установил содержимое в свойстве ContentTemplate элемента HeaderedContentControl (DraggablePanel в моем коде).

+1 Дэви в любом случае поможет мне пройти через это.

Ответ 2

Убедитесь, что вы создаете новый объект табуляции, и вы не пытаетесь вставить одну и ту же вкладку в элемент управления вкладки во второй раз. Элемент управления может иметь только 1 родительский элемент, и кажется, что проблема заключается в том, что вы пытаетесь вставить вкладку в два разных контейнера или, более вероятно, один и тот же элемент управления вкладки дважды.

Ответ 3

Чтобы не все вышесказанное, короткий ответ: вам нужно изменить Content на Template (в вашем XAML либо в стиле, либо в прямом объявлении ContentControl).