为什么在列表框数据模板中使用自定义控件时会出现异常
Why do I get an exception when using custom control in a listbox datatemplate
基本上,我创建了非常简单的自定义控件,它源自弹出窗口。我想在列表框数据模板中使用该弹出窗口,因此每个列表框项目都会有它。但我收到此错误消息
"Specified element is already the logical child of another element. Disconnect it first",我知道这条消息是什么意思,我过去不得不处理这个问题。但是在这种特定情况下,我不明白为什么我首先得到它。
public class MyPopup : Popup
{
static MyPopup()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyPopup), new FrameworkPropertyMetadata(typeof(MyPopup)));
}
}
它的样式(在通用文件中)
<Style x:Key="MyPopupStyle" TargetType="{x:Type local:MyPopup}">
<Setter Property="Placement" Value="MousePoint" />
<Setter Property="Child">
<Setter.Value>
<Border
Width="100"
Height="100"
Background="HotPink" />
</Setter.Value>
</Setter>
<Setter Property="IsOpen" Value="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.IsMouseOver, Mode=OneWay}" />
</Style>
主窗口
<Window.Resources>
<DataTemplate x:Key="Foo">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="TextBlock" Text="Hover over" />
<wpfApp1:MyPopup PlacementTarget="{Binding ElementName=TextBlock}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox ItemTemplate="{StaticResource Foo}" ItemsSource="{Binding MyList}" />
代码隐藏
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
MyList = new List<string>{"Dan","John","Test"};
DataContext = this;
}
public List<string> MyList { get; }
}
如果我将此自定义控件更改为从控件派生并将 Popup 放入其控件模板中,那么它就可以正常工作,但是在使用此视图时我丢失了我想从此弹出窗口访问的属性。我知道我可以创建依赖属性来绕过它,但理想情况下我想知道这里发生了什么。谢谢。
您的 Style
将 Border
的单个实例设置为所有 MyPopup
的子实例。
WPF 控件只能有一个父控件;那行不通。
相反,您需要使用 ControlTemplate 或 DataTemplate,它们将为每个控件实例制作其内容的单独副本。
基本上,我创建了非常简单的自定义控件,它源自弹出窗口。我想在列表框数据模板中使用该弹出窗口,因此每个列表框项目都会有它。但我收到此错误消息 "Specified element is already the logical child of another element. Disconnect it first",我知道这条消息是什么意思,我过去不得不处理这个问题。但是在这种特定情况下,我不明白为什么我首先得到它。
public class MyPopup : Popup
{
static MyPopup()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyPopup), new FrameworkPropertyMetadata(typeof(MyPopup)));
}
}
它的样式(在通用文件中)
<Style x:Key="MyPopupStyle" TargetType="{x:Type local:MyPopup}">
<Setter Property="Placement" Value="MousePoint" />
<Setter Property="Child">
<Setter.Value>
<Border
Width="100"
Height="100"
Background="HotPink" />
</Setter.Value>
</Setter>
<Setter Property="IsOpen" Value="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.IsMouseOver, Mode=OneWay}" />
</Style>
主窗口
<Window.Resources>
<DataTemplate x:Key="Foo">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="TextBlock" Text="Hover over" />
<wpfApp1:MyPopup PlacementTarget="{Binding ElementName=TextBlock}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox ItemTemplate="{StaticResource Foo}" ItemsSource="{Binding MyList}" />
代码隐藏
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
MyList = new List<string>{"Dan","John","Test"};
DataContext = this;
}
public List<string> MyList { get; }
}
如果我将此自定义控件更改为从控件派生并将 Popup 放入其控件模板中,那么它就可以正常工作,但是在使用此视图时我丢失了我想从此弹出窗口访问的属性。我知道我可以创建依赖属性来绕过它,但理想情况下我想知道这里发生了什么。谢谢。
您的 Style
将 Border
的单个实例设置为所有 MyPopup
的子实例。
WPF 控件只能有一个父控件;那行不通。
相反,您需要使用 ControlTemplate 或 DataTemplate,它们将为每个控件实例制作其内容的单独副本。