We've got a few Custom Controls with their own styles, templates. Basically something like that: (I'll post the full styles/templates at the end)
public class CustomBtn : Button
{
public propdp DependencyProp1...
public propdp DependencyProp2...
...
}
<Style x:Key="XStyle.CustomBtnStyle" TargetType="{x:Type cc:CustomBtn}">
...
<Setter Property="Template" Value="{StaticResource XControlTemplate.CustomButton}"/>
<ControlTemplate x:Key="XControlTemplate.CustomButton" TargetType="{x:Type cc:CustomBtn}">
...
Some of the properties defined are used in the templates, some in the styles proper.
The issue we've been facing is that those controls will not display in the designer (most of the time), instead showing as if they're broken. With the error being "Target type does not match type of element"
- There are no issues at run time
- There are no private/none default constructors in any of our custom controls.
- I've got an updated DesignTimeResources
- There's a strange discrepancy I've noticed in the error, between the numbers following the control name
There are a bunch of similar questions out there, but the answers attached did not work/apply for me.
Although sometimes after tinkering with the styles/classes the designer will display them in a very basic form.. until it doesn't again.
Styles, classes (apologies for the wall of code):
public class ButtonIcon : Button { // VisualTheme determines color theme public EVisualTheme VisualTheme { get { return (EVisualTheme)GetValue(VisualThemeProperty); } set { SetValue(VisualThemeProperty, value); } }
// Using a DependencyProperty as the backing store for VisualTheme. This enables animation, styling, binding, etc... public static readonly DependencyProperty VisualThemeProperty = DependencyProperty.Register("VisualTheme", typeof(EVisualTheme), typeof(ButtonIcon), new PropertyMetadata(EVisualTheme.Common)); // Icon for Button public Geometry IconGeometry { get { return (Geometry)GetValue(IconGeometryProperty); } set { SetValue(IconGeometryProperty, value); } } // Using a DependencyProperty as the backing store for IconGeometry. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconGeometryProperty = DependencyProperty.Register("IconGeometry", typeof(Geometry), typeof(ButtonIcon), new PropertyMetadata(new PathGeometry())); public double IconSize { get { return (double)GetValue(IconSizeProperty); } set { SetValue(IconSizeProperty, value); } } // Using a DependencyProperty as the backing store for IconSize. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconSizeProperty = DependencyProperty.Register("IconSize", typeof(double), typeof(ButtonIcon), new PropertyMetadata(40.0)); // Text to be set on Button public object Caption { get { return (object)GetValue(CaptionProperty); } set { SetValue(CaptionProperty, value); } } // Using a DependencyProperty as the backing store for Caption. This enables animation, styling, binding, etc... public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(object), typeof(ButtonIcon), new PropertyMetadata(null)); // For running Animations from 0 to 1 in order to change Animation property during Runtime (see examples of usage in code) public double GradientPercentage { get { return (double)GetValue(GradientPercentageProperty); } set { SetValue(GradientPercentageProperty, value); } } // Using a DependencyProperty as the backing store for GradientPercentage. This enables animation, styling, binding, etc... public static readonly DependencyProperty GradientPercentageProperty = DependencyProperty.Register("GradientPercentage", typeof(double), typeof(ButtonIcon), new PropertyMetadata(0.0)); public Point IconRenderTransformOrigin { get { return (Point)GetValue(IconRenderTransformOriginProperty); } set { SetValue(IconRenderTransformOriginProperty, value); } } // Using a DependencyProperty as the backing store for IconRenderTransformOrigin. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconRenderTransformOriginProperty = DependencyProperty.Register("IconRenderTransformOrigin", typeof(Point), typeof(ButtonIcon), new PropertyMetadata(new Point(0.5, 0.5))); // Angle at which to rotate Icon public double IconRotationAngle { get { return (double)GetValue(IconRotationAngleProperty); } set { SetValue(IconRotationAngleProperty, value); } } // Using a DependencyProperty as the backing store for IconRotationAngle. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconRotationAngleProperty = DependencyProperty.Register("IconRotationAngle", typeof(double), typeof(ButtonIcon), new PropertyMetadata(0.0)); // CenterX for Icon rotation public double IconRotationCenterX { get { return (double)GetValue(IconRotationCenterXProperty); } set { SetValue(IconRotationCenterXProperty, value); } } // Using a DependencyProperty as the backing store for IconRotationCenterX. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconRotationCenterXProperty = DependencyProperty.Register("IconRotationCenterX", typeof(double), typeof(ButtonIcon), new PropertyMetadata(0.0)); // CenterY for Icon rotation public double IconRotationCenterY { get { return (double)GetValue(IconRotationCenterYProperty); } set { SetValue(IconRotationCenterYProperty, value); } } // Using a DependencyProperty as the backing store for IconRotationCenterY. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconRotationCenterYProperty = DependencyProperty.Register("IconRotationCenterY", typeof(double), typeof(ButtonIcon), new PropertyMetadata(0.0)); // ScaleX of Icon public double IconScaleX { get { return (double)GetValue(IconScaleXProperty); } set { SetValue(IconScaleXProperty, value); } } // Using a DependencyProperty as the backing store for IconScaleX. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconScaleXProperty = DependencyProperty.Register("IconScaleX", typeof(double), typeof(ButtonIcon), new PropertyMetadata(1.0)); // ScaleY of Icon public double IconScaleY { get { return (double)GetValue(IconScaleYProperty); } set { SetValue(IconScaleYProperty, value); } } // Using a DependencyProperty as the backing store for IconScaleY. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconScaleYProperty = DependencyProperty.Register("IconScaleY", typeof(double), typeof(ButtonIcon), new PropertyMetadata(1.0)); // CenterX for Icon scale public double IconScaleCenterX { get { return (double)GetValue(IconScaleCenterXProperty); } set { SetValue(IconScaleCenterXProperty, value); } } // Using a DependencyProperty as the backing store for IconScaleCenterX. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconScaleCenterXProperty = DependencyProperty.Register("IconScaleCenterX", typeof(double), typeof(ButtonIcon), new PropertyMetadata(0.0)); // CenterY for Icon scale public double IconScaleCenterY { get { return (double)GetValue(IconScaleCenterYProperty); } set { SetValue(IconScaleCenterYProperty, value); } } // Using a DependencyProperty as the backing store for IconScaleCenterY. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconScaleCenterYProperty = DependencyProperty.Register("IconScaleCenterY", typeof(double), typeof(ButtonIcon), new PropertyMetadata(0.0)); public double IconTranslateX { get { return (double)GetValue(IconTranslateXProperty); } set { SetValue(IconTranslateXProperty, value); } } // Using a DependencyProperty as the backing store for IconTranslateX. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconTranslateXProperty = DependencyProperty.Register("IconTranslateX", typeof(double), typeof(ButtonIcon), new PropertyMetadata(0.0)); public double IconTranslateY { get { return (double)GetValue(IconTranslateYProperty); } set { SetValue(IconTranslateYProperty, value); } } // Using a DependencyProperty as the backing store for IconTranslateY. This enables animation, styling, binding, etc... public static readonly DependencyProperty IconTranslateYProperty = DependencyProperty.Register("IconTranslateY", typeof(double), typeof(ButtonIcon), new PropertyMetadata(0.0));}
<Style x:Key="XStyle.ButtonIcon.Action" TargetType="{x:Type cc:ButtonIcon}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Height" Value="{StaticResource XDouble.Height.Button.Default}"/>
<Setter Property="Template" Value="{StaticResource XControlTemplate.ButtonIcon.Action}"/>
<Setter Property="IconSize" Value="30"/>
<Setter Property="GradientPercentage" Value="0.0"/>
<Setter Property="IconGeometry" Value="{x:Null}"/>
<Setter Property="FontSize" Value="{StaticResource XDouble.FontSize.Header3}"/>
<Setter Property="Foreground" Value="{Binding VisualTheme, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type cc:ButtonIcon}}, Converter={rconv:VisualThemeToForegroundConverter}}"/>
<Setter Property="BorderBrush" Value="{StaticResource XBrush.Frame}"/>
<Setter Property="BorderThickness" Value="0"/>
<Style.Triggers>
<Trigger Property="VisualTheme" Value="ListItem">
<Setter Property="BorderThickness" Value="{StaticResource XThickness.Border.Frame}"/>
</Trigger>
<Trigger Property="VisualTheme" Value="DarkOnLight">
<Setter Property="BorderThickness" Value="{StaticResource XThickness.Border.Frame}"/>
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="XControlTemplate.ButtonIcon.Action" TargetType="{x:Type cc:ButtonIcon}">
<Border
x:Name="OuterBorder"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
BorderBrush="{TemplateBinding BorderBrush}"
Padding="10,0"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{StaticResource XCornerRadius.Frame}">
<Border.Background>
<MultiBinding Converter="{rconv:PercentageToBrushConverter}">
<Binding Path="GradientPercentage" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type cc:ButtonIcon}}" />
<Binding Path="VisualTheme" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type cc:ButtonIcon}}" />
</MultiBinding>
</Border.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="IconColumn" Width="Auto" />
<ColumnDefinition x:Name="SpacerColumn" Width="10" />
<ColumnDefinition x:Name="CaptionColumn" Width="*" />
</Grid.ColumnDefinitions>
<Border
x:Name="IconBorder"
Width="{TemplateBinding IconSize}"
Height="{TemplateBinding IconSize}"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Path
x:Name="IconPart"
Data="{TemplateBinding IconGeometry}"
Fill="{TemplateBinding Foreground}"
RenderTransformOrigin="{Binding Path=IconRenderTransformOrigin, RelativeSource={RelativeSource TemplatedParent}}"
Stretch="Uniform">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform
CenterX="{Binding Path=IconScaleCenterX, RelativeSource={RelativeSource TemplatedParent}}"
CenterY="{Binding Path=IconScaleCenterY, RelativeSource={RelativeSource TemplatedParent}}"
ScaleX="{Binding Path=IconScaleX, RelativeSource={RelativeSource TemplatedParent}}"
ScaleY="{Binding Path=IconScaleY, RelativeSource={RelativeSource TemplatedParent}}" />
<RotateTransform
Angle="{Binding Path=IconRotationAngle, RelativeSource={RelativeSource TemplatedParent}}"
CenterX="{Binding Path=IconRotationCenterX, RelativeSource={RelativeSource TemplatedParent}}"
CenterY="{Binding Path=IconRotationCenterY, RelativeSource={RelativeSource TemplatedParent}}" />
</TransformGroup>
</Path.RenderTransform>
</Path>
</Border>
<ContentPresenter
x:Name="ContentPresenter"
Grid.Column="2"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{TemplateBinding Caption}"
Focusable="False"
SnapsToDevicePixels="True"
TextBlock.FontSize="{TemplateBinding FontSize}"
TextBlock.Foreground="{TemplateBinding Foreground}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="{StaticResource XDouble.Opacity.Disabled}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="StoryBoardMouseEnter" Storyboard="{StaticResource XStoryboard.DoubleAnimation.GradientPercentage.RunUp}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard x:Name="StoryBoardMouseLeave" Storyboard="{StaticResource XStoryboard.DoubleAnimation.GradientPercentage.RunDown}" />
</Trigger.ExitActions>
</Trigger>
<Trigger Property="Caption" Value="{x:Null}">
<Setter TargetName="ContentPresenter" Property="Visibility" Value="Collapsed" />
<Setter TargetName="IconColumn" Property="Width" Value="*" />
<Setter TargetName="SpacerColumn" Property="Width" Value="0" />
<Setter TargetName="CaptionColumn" Property="Width" Value="0" />
</Trigger>
<Trigger Property="Caption" Value="">
<Setter TargetName="ContentPresenter" Property="Visibility" Value="Collapsed" />
<Setter TargetName="IconColumn" Property="Width" Value="*" />
<Setter TargetName="SpacerColumn" Property="Width" Value="0" />
<Setter TargetName="CaptionColumn" Property="Width" Value="0" />
</Trigger>
<Trigger Property="IconGeometry" Value="{x:Null}">
<Setter TargetName="IconPart" Property="Visibility" Value="Collapsed"/>
<Setter TargetName="SpacerColumn" Property="Width" Value="0"/>
<Setter TargetName="IconColumn" Property="Width" Value="0"/>
<Setter TargetName="ContentPresenter" Property="Grid.Column" Value="0"/>
<Setter TargetName="ContentPresenter" Property="Grid.ColumnSpan" Value="3"/>
<Setter TargetName="ContentPresenter" Property="HorizontalAlignment" Value="Center"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

