我有一个TabControl,每个标签可以包含相同的UI但具有不同的数据。在任何选项卡中,用户都可以单击按钮并弹出一个弹出窗口。这将Style属性设置为ViewModel,告诉它用于弹出UI的样式。 Style绑定到附加到自定义PopupUserControl的自定义DependecyProperty。我的问题是,当弹出窗口的第二个副本在另一个选项卡中打开时,我得到以下错误(无论应用什么样式):
指定元素已经是 另一个元素的逻辑子。 首先断开它。
ButtonClick命令:
MyViewModel vm = ((Button)sender).DataContext as MyViewModel;
if (vm != null)
{
Style popupStyle = (Style)Application.Current.FindResource("SomePopupStyle");
vm.EditPanelStyle= popupStyle ;
}
这会触发Style
上的PropertyChange事件public Style EditPanelStyle
{
get { return _editPanelStyle; }
set
{
if (_editPanelStyle != value)
{
_editPanelStyle = value;
OnPropertyChanged("EditPanelStyle");
}
}
}
这会触发ViewModelBase中的OnPropertyChanged事件
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
错误发生在ViewModelBase
中的第handler(this, e);
行
修改
TabItem包含一个Canvas和一堆可以添加/删除/移动/等的面板。每个Panel都有自己的资源目录。从Panel中我可以设置PopupStyle就好了,它可以毫无问题地应用。面板中使用的样式也在PanelResourceDictionary中定义。
与失败者和成功者的主要区别在于Style位于不同的位置。
编辑#2 失败的样式 - LookupDialog是一个自定义的WPF UserControl
<!-- 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's created from standard WPF controls with nothing special -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
答案 0 :(得分:20)
我的问题是我在我的样式中设置了Content
,Content
不能有多于一个逻辑父级。我需要将其移至Template
。由于我不想丢失基本样式,因此我将内容设置在HeaderedContentControl的ContentTemplate
属性中(我的代码中的DraggablePanel)。
给Davy +1,无论如何帮助我走过这条路。
答案 1 :(得分:8)
确保您正在创建新的标签对象,而不是第二次尝试将相同的标签插入标签控件。一个控件只能有1个父控件,看起来问题是你试图将一个选项卡插入到两个不同的容器中,或者更可能是两个相同的选项卡控件。
答案 2 :(得分:-1)
如果不能阅读以上所有内容,简短的回答是:您需要将Content
更改为Template
(在您的XAML中,无论是样式还是直接声明ContentControl
)。