0

I'd like to create a custom control based on StackPanel since I need to add some code to the derived class.

I created the custom control in Visual Studio.

When I want to use the custom control in an XAML I get various errors.

I'm new to WPF.

Is it (not) possible to use a customized WPF control just like its base class in XAML (StackPanel in this case) ?

c# code is

namespace MyNameSpace
{
    public class AbstractForm : StackPanel
    {
        static AbstractForm()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(AbstractForm), new FrameworkPropertyMetadata(typeof(AbstractForm)));
        }
        protected override Size MeasureOverride(Size constraint)
        {
            return base.MeasureOverride(constraint);
        }
        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            return base.ArrangeOverride(arrangeBounds);
        }
        // more code
    }
}

Generic.xaml content is (most parts generated when creating the custom control):

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

    <Style TargetType="{x:Type local:AbstractForm}"
        BasedOn = "{StaticResource {x:Type StackPanel}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:AbstractForm}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

I then try to use "AbstractForm" like a StackPanel in MainWindow.xaml:

<Window x:Name="MyApp" x:Class="MyNameSpace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:control="clr-namespace:MyNameSpace"
        mc:Ignorable="d"
        Title="MyApp" BorderBrush="{DynamicResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}">
    <StackPanel x:Name="MyAppUI" Orientation = "vertical" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top">
        <control:AbstractForm x:Name="HeaderArea" Orientation = "horizontal" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top">
            <Image x:Name="appImage" HorizontalAlignment="Left" VerticalAlignment="Top" Source = "AppImage.gif"/>
            <StackPanel Orientation = "vertical" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top">
                <!-- more content -->
            </StackPanel>
        </control:AbstractForm>
        <!-- more content -->
    </StackPanel>
</Window>

When running my application I see the following errors (trying to re-translate from german):

  • The 'Orientation' property was not found in 'AbstractForm'
  • Element 'Orientation' not recognized or not accessable
  • Property "Orientation" not contained in XML-Namespace "clr-namespace:MyNameSpace". Row ... column ...
  • No content can be added to object of type "AbstractForm" (i.e. the <Image and another <StackPanel)
user7399085
  • 220
  • 1
  • 12
  • Take a look at: https://stackoverflow.com/questions/269106/inheriting-from-a-usercontrol-in-wpf. You can't inherit the Xaml part, only the code-behind – JayV May 01 '18 at 13:35
  • Maybe you could create a Custom Control and add a stackpanel to the xaml?? And then extend StackPanel in the c# code – Youri Leenman May 01 '18 at 13:47
  • You cannot define a control template (`ControlTemplate`) for a `StackPanel` because it is not a control (does not derive from `System.Window.Controls.Control` class). You can create a custom/user control that has the StackPanel as a child. – user1672994 May 01 '18 at 13:48
  • This isn't a beginner level task. You might find this page and it's links interesting though. https://www.wpftutorial.net/CustomLayoutPanel.html – Andy May 01 '18 at 17:59

1 Answers1

2

A StackPanel is not derived from Control and has therefore no Template property. Hence the ResourceDictionary does not compile.

Remove the Setter from the default Style, then rebuild your project.

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

    <Style TargetType="{x:Type local:AbstractForm}"
           BasedOn="{StaticResource {x:Type StackPanel}}">
    </Style>
</ResourceDictionary>

It is also questionable if you need a default Style for your AbstractForm class at all.

If not, just delete the entire Generic.xaml file and the static constructor that overrides the default value of the DefaultStyleKey property. In other words, simply create a class derived from StackPanel.

Clemens
  • 123,504
  • 12
  • 155
  • 268