Click here to Skip to main content
15,881,089 members
Articles / Desktop Programming / WPF
Tip/Trick

Writing Custom Control with New WPF XAML Designer

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
9 Feb 2023CPOL2 min read 10.1K   178   13   2
How to either migrate to the new XAML designer extensibility or write WPF custom control extensibility model based on .designtools.dll.
The current WPF XAML Designer for .NET Framework has been deprecated and will be replaced with a new WPF XAML Designer for .NET Framework, based on the same architecture used for the WPF XAML Designer for .NET (.NET Core).

Introduction

Simplified example of making a custom button with the new WPF .NET Framework control extensibility model based on .designtools.dll extension in .NET7 (Core) using a new WPF XAML Designer. With this example, I want to simplify example provided by Microsoft, and put focus only on main things when someone wants to create custom control extensibility model based on .designtools.dll.

Background

Since Visual Studio 2022, the WPF .NET Framework control extensibility model based on .design.dll and Microsoft.Windows.Design.Extensibility is no longer supported. You can read more about it in New WPF XAML Designer for .NET Framework, or in XAML designer extensibility migration. This article is mostly copy / paste from already mentioned Microsoft sample, and the article. In order to try to stick to the Keep It Simple principle, I will not copy paste more information from Microsoft.

Using the Code

This example was made using Visual Studio 2022. It will not work in previous versions of Visual Studio and there will be one class library (.NET Framework) project and one WPF Custom Control Library needed:

  1. CustomControlLibrary.WpfCore - WPF Custom Control Library
  2. CustomControlLibrary.WpfCore.DesignTools - Please notice that extension .DesignTools is necessary, and that the project is in .NET Framework 4.8. This DLL will be later copied in Design subfolder.
  3. Rebuild and create package from CustomControlLibrary.WpfCore (right mouse button -> pack).
  4. At the end, NuGet packet should be installed in host application, in order to see the result:

    and to populate ToolBox.

To test the result, you can use also CustomControlLibrary.WpfCore.Host application. *.DesignTools.dll files should be either in the same folder like main application, or like in my case, in the same Design subfolder, like Microsoft explained here. That means that in main folder, I have CustomControlLibrary.WpfCore.dll and in Design subfolder CustomControlLibrary.WpfCore.DesignTools.dll, like in my example.

CustomControlLibrary.WpfCore

  1. Create WPF Custom Control Library and change csproj to look like:
    XML
    <Project Sdk="Microsoft.NET.Sdk">
    
        <PropertyGroup>
            <TargetFramework>net7.0-windows</TargetFramework>
            <Nullable>enable</Nullable>
            <UseWPF>true</UseWPF>
        </PropertyGroup>
    
        <ItemGroup>
            <PackageReference Include="NuGet.Build.Packaging" Version="0.2.2">
                <PrivateAssets>all</PrivateAssets>
                <IncludeAssets>runtime; build; native; contentfiles; 
                 analyzers; buildtransitive</IncludeAssets>
            </PackageReference>
        </ItemGroup>
    
        <PropertyGroup>
            <PackageId>CustomControlLibrary.WpfCore</PackageId>
            <Description>Button example</Description>
        </PropertyGroup>
    
        <ItemGroup>
            <PackageFile Include="VisualStudioToolsManifest.xml">
                <Kind>Tools</Kind>
            </PackageFile>
            <PackageFile Include=
             "$(OutputPath)\CustomControlLibrary.WpfCore.DesignTools.dll">
                <Kind>Lib</Kind>
                <TargetPath>Design\CustomControlLibrary.WpfCore.DesignTools.dll
                </TargetPath>
            </PackageFile>
        </ItemGroup>
    
    </Project>

    Here notice:

    XML
    <TargetPath>Design\CustomControlLibrary.WpfCore.DesignTools.dll</TargetPath>

    with this line, I am packing DesignTools.dll into Design subfolder.

  2. Rename CustomControl1 to MyButton, also in Generic.xaml.
  3. Add VisualStudioToolsManifest.xml.

MyButton

C#
using System.Windows;
using System.Windows.Controls;

namespace CustomControlLibrary.WpfCore
{
    public class MyButton : Button
    {
        public static DependencyProperty RenderActiveProperty;

        public bool RenderActive
        {
            get { return (bool)GetValue(RenderActiveProperty); }
            set { SetValue(RenderActiveProperty, value); }
        }

        static MyButton()
        {
            RenderActiveProperty = DependencyProperty.Register("RenderActive",
                typeof(bool),
                typeof(MyButton),
                new PropertyMetadata(false));
        }

        public string Test { get; set; }
    }
}

VisualStudioToolsManifest

This file is needed to populate ToolBox like Microsoft explained here. After installing NuGet paket in the host application, you should see something like:

XML
<FileList>
    <File Reference="CustomControlLibrary.WpfCore.dll">
        <ToolboxItems UIFramework="WPF" VSCategory="CustomControlLibrary.WpfCore" 
         BlendCategory="CustomControlLibrary.WpfCore">
            <Item Type="CustomControlLibrary.WpfCore.MyButton" />
        </ToolboxItems>
    </File>
</FileList>

CustomControlLibrary.WpfCore.DesignTools

  1. Install NuGet package Microsoft.VisualStudio.DesignTools.Extensibility:
    Install-Package Microsoft.VisualStudio.DesignTools.Extensibility 
           -Version 17.4.33103.184
  2. Rename Class1 to MyDesignMetadata:
    C#
    using Microsoft.VisualStudio.DesignTools.Extensibility.Metadata;
    using System.ComponentModel;
    
    [assembly: ProvideMetadata(typeof
               (XAMLDesignerExtensibilityCore.DesignTools.MyDesignMetadata))]
    namespace XAMLDesignerExtensibilityCore.DesignTools
    {
        public class MyDesignMetadata : IProvideAttributeTable
        {
            public AttributeTable AttributeTable
            {
                get
                {
                    AttributeTableBuilder builder = new AttributeTableBuilder();
    
                    builder.AddCustomAttributes("CustomControlLibrary.WpfCore.MyButton"
                        , "Test"
                        , new CategoryAttribute("** test **")
                    );
    
                    return builder.CreateTable();
                }
            }
        }
    }
  3. Set build output path to something like ..\CustomControlLibrary.WpfCore\bin\Debug\net7.0-windows\ or copy it manually to CustomControlLibrary.WpfCore output folder.

History

  • 10th February, 2023: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWhat about .NET6 support? Pin
Cosmico7812-May-23 0:38
Cosmico7812-May-23 0:38 
AnswerRe: What about .NET6 support? Pin
Stanko Milošev12-May-23 1:05
Stanko Milošev12-May-23 1:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.