C# Silverlight嵌套自定义控件导致StackOverflowException
我正在为我的Silverlight项目编写一个可重用的Controllibrary。目前,每次启动使用Controllibrary的测试应用程序时,我都会收到一个StackOverflowException。我能够在一个小样本项目中重现异常 我有两个简单的自定义控件:C# Silverlight嵌套自定义控件导致StackOverflowException,c#,xaml,silverlight,controls,stack-overflow,C#,Xaml,Silverlight,Controls,Stack Overflow,我正在为我的Silverlight项目编写一个可重用的Controllibrary。目前,每次启动使用Controllibrary的测试应用程序时,我都会收到一个StackOverflowException。我能够在一个小样本项目中重现异常 我有两个简单的自定义控件: //Control1.cs public class Control1:Control { public Control1() { this.DefaultStyleKey = typeof(Con
//Control1.cs
public class Control1:Control
{
public Control1()
{
this.DefaultStyleKey = typeof(Control1);
}
}
//Control2.cs
public class Control2:Control
{
public static DependencyProperty TestProperty =
DependencyProperty.Register("Test",typeof(Control1),typeof(Control2),null);
public Control1 Test
{
get {return (Control1)GetValue(TestProperty);}
set {SetValue(TestProperty,value);}
}
public Control2()
{
this.DefaultStyleKey = typeof(Control2);
}
}
//generic.xaml
<Style TargetType="local:Control1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Control1">
<Rectangle Width="20" Height="20" Fill="Blue"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:Control2">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Control2">
<Rectangle Width="20" Height="20" Fill="Red"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Test">
<Setter.Value>
<local:Control1/>
</Setter.Value>
</Setter>
</Style>
CONTROL2具有Control1类型的DependencyProperty。在我的Controllibrary中,Control1与菜单项类似,当按下Control2时,菜单项会被传递到菜单项。
现在,在my Themes/generic.xaml iam中,为控件定义了两种默认样式:
//Control1.cs
public class Control1:Control
{
public Control1()
{
this.DefaultStyleKey = typeof(Control1);
}
}
//Control2.cs
public class Control2:Control
{
public static DependencyProperty TestProperty =
DependencyProperty.Register("Test",typeof(Control1),typeof(Control2),null);
public Control1 Test
{
get {return (Control1)GetValue(TestProperty);}
set {SetValue(TestProperty,value);}
}
public Control2()
{
this.DefaultStyleKey = typeof(Control2);
}
}
//generic.xaml
<Style TargetType="local:Control1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Control1">
<Rectangle Width="20" Height="20" Fill="Blue"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:Control2">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Control2">
<Rectangle Width="20" Height="20" Fill="Red"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Test">
<Setter.Value>
<local:Control1/>
</Setter.Value>
</Setter>
</Style>
//generic.xaml
现在,当我在测试应用程序中使用Control2时,我得到一个StackOverflowException。设置断点时,将调用Control2的构造函数一次,然后继续调用Control1的构造函数,直到StackOverflowException
当我将Control1s构造函数更改为直接从带有resourceKey的ResourceDictionary加载其样式时,一切都可以正常加载。但这更像是一种变通办法,而不是解决方案
当我在generic.xaml中删除TestProperty的Setter时,一切都可以正常工作。然后,我可以覆盖测试应用程序的my App.xaml中的样式,并在那里定义TestProperty的Setter。但这也不是我想做的
没有人能解决这个问题吗?
或者某个人可以解释为什么它会这样
提前感谢我自己也偶然发现了这一美妙的效果,结果是: 您不能在
ResourceDictionary
中实例化从UIElement
派生的对象(您的行
正好尝试了这一点)(generic.xaml是其中之一),因为所述字典中的所有对象都必须是可共享的
记录在案。相关章节:
可共享类型和UIElement类型
资源字典是一种定义可共享类型和
这些类型在XAML中的值。并非所有类型或值都适用
从ResourceDictionary获取用法。欲了解更多关于
类型在Silverlight中被认为是可共享的,请参阅参考资料
字典
特别是,所有UIElement派生类型都不可共享,除非
它们来自于模板和模板在特定领域的应用
控件实例。不包括模板案例,需要UIElement
实例化后仅存在于对象树中的一个位置,以及
让UIElement可共享可能会违反这一点
原则
但是有一种治疗方法
将控件1包装在数据模板中
,使控件1不会在资源字典
中实例化,而是在实际实例化控件2时实例化
<Style TargetType="OuterControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="OuterControl">
<StackPanel>
<TextBlock Text="Outer Hello World"/>
<ContentPresenter
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<InnerControl/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
这正是我想要的答案。谢谢