iam writing a reusable Controllibrary for my Silverlight Projects. At the moment i get an StackOverflowException each Time i startup my test Application wich is using the Controllibrary. I was able to reproduce the Exception in a small sample Projekt.
I have two simple Custom Controls:
//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);
}
}
Constrol2 has a DependencyProperty of Type Control1. In my Controllibrary Control1 is something simelar to a MenuItem which is passed to the Menu when Control2 is pressed. Now in my Themes/generic.xaml iam defining the two default Styles for the Controls:
//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>
Now when i use Control2 in a Test Application iam getting a StackOverflowException. When setting up Breakpoints the Constructor of Control2 is called once an then the Constructor of Control1 is called continuesly until the StackOverflowException.
When i change Control1s constructor to load its style directly from a ResourceDictionary with a resourceKey everything loads fine. But that is more like a Workaround than a Solution.
When i remove the Setter for my TestProperty in the generic.xaml everthing works fine as well. Then iam able to override the Style in my App.xaml of the Test Application and define the Setter for the TestProperty there. But thats also not what i want to do.
Does annyone have a Solution for this Problem? Or maybe an someone can explain me why it behaves that way.
Thanks in advance
I stumbled upon that splendid effect myself, and as it turned out:
You can't instantiate an object derived from
UIElement
(your line<local:Control1/>
tries exactly this) in aResourceDictionary
(and generic.xaml is one), because all objects in said dictionary must be shareable.Documented here. Relevant section:
But there is a cure
Wrap your control1 in a
DataTemplate
, causing your control1 to not be instantiated in theResourceDictionary
but rather at the point in time when a control2 is actually instantiated.and code