views:

483

answers:

2

I have a custom control library where I have several custom controls that I use in my main application. I have a simple custom control that lets the user select pen thickness values from a combobox. Now, I am creating a new custom control, based on a listbox, and I want to include the pen thickness combobox in the new custom control's ItemTemplate.

I am getting this error:

"Cannot create instance of "LineThicknessComboBox" defined in assembly CustomControls ... Exception has been thrown by the target of an invocation. Error at object "10_T" in markup file 'CustomControls;component/Themes/CustomListBox.General.xaml'.

Here is the XAML and code behind for the LineThicknessComboBox:

namespace CustomControls
{
    public class LineThicknessComboBox : ComboBox
    {
        public LineThicknessComboBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(LineThicknessComboBox)
                        , new FrameworkPropertyMetadata(typeof(LineThicknessComboBox)));

        }
    }
}

and in LineThicknessCombobox.Generic.xaml:

<ResourceDictionary 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls">

<Style TargetType="{x:Type local:LineThicknessComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}">
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                ...
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

</ResourceDictionary>

Here is the XAML and codebehind for my new CustomListBox:

namespace CustomControls
{
    public class CustomListBox : ListBox
    {
        public CustomListBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomListBox)
                        , new FrameworkPropertyMetadata(typeof(CustomListBox)));
        }
    }
}

and in CustomListBox.Generic.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls">

<Style TargetType="{x:Type local:CustomListBox}" BasedOn="{StaticResource {x:Type ListBox}}">
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <Border>
                 ...
                     <local:LineThicknessComboBox />
                 ...  
                </Border>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

</ResourceDictionary>

And here is my Generix.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="CustomControls;component/Themes/LineThicknessComboBox.Generic.xaml"/>
        <ResourceDictionary Source="CustomControls;component/Themes/CustomListBox.Generic.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

I'm thinking I have some kind of reference problem, but can't figure out what is wrong. The program compiles and runs without any warnings/errors but when the CustomListBox is created in my main application, I get the error listed above. Without including the LineThicknessComboBox, the CustomListBox works fine.

Can anyone explain why I am getting this error? It is possible to include my custom control in another, even though they are in the same custom control library, correct?

Thanks!

A: 

You might be running into a problem with DesignMode and code in you're constructor. I can't say for certain, as I have had my fair share of problems with WPF user controls and the design surface, and all of them have cryptic errors like this.

The solution is to use the System.ComponentModel.DesignerProperties class to check if you are in design mode, and wrap any code that does not function in design mode in an if block to prevent it from running:

namespace CustomControls
{
    public class LineThicknessComboBox : ComboBox
    {
        public LineThicknessComboBox()
        {
            // Design-mode capable code...

            if (DesignerProperties.GetIsInDesignMode(this)) return;

            // Design mode incapable code...

            DefaultStyleKeyProperty.OverrideMetadata(typeof(LineThicknessComboBox)
                        , new FrameworkPropertyMetadata(typeof(LineThicknessComboBox)));

        }
    }
}
jrista
I don't think this is my problem, since I am getting the error at runtime. Thanks for the reply though.
stevosaurus
A: 

// i think it should be static constructor in both cases because dependency property metadata overriding must always be done in static constructor.

// not public LineThicknessComboBox()
static LineThicknessComboBox()        
{
            DefaultStyleKeyProperty.OverrideMetadata(
               typeof(LineThicknessComboBox)
                        , new FrameworkPropertyMetadata(
                              typeof(LineThicknessComboBox)));
}

Calls to OverrideMetadata should only be performed within the static constructors of the type that provides itself as the forType parameter of this method, or through similar instantiation. Attempting to change metadata after instances of the owner type exist will not raise exceptions, but will result in inconsistent behaviors in the property system.

FROM MSDN

Akash Kava
I'll give this a shot when I get home later today. Thanks for the heads up, I'm not sure why my constructors aren't declared static.
stevosaurus
This fixed my problem, thanks Akash.
stevosaurus