Skip to content

Sample Development

Arlo Godfrey edited this page Mar 12, 2024 · 2 revisions

This document describes how to add a new sample page for a new control you want to add to the toolkit.

How it works

Each component directory has a corresponding samples folder which contains the YourComponentName.Samples project. This is a separate project that references the component, and is where all the samples and docs displayed in the sample app for your component will go.

The sample projects make use of the CommunityToolkit.Tooling.SampleGen source generator to:

  • Expedite the process of building new samples, without cluttering the code.
  • Embed them as interactive samples inside your documentation.
  • Collect both samples and sample docs for display in the sample gallery.

The SampleGen source generator will automatically find all sample controls and sample markdown pages in your sample project, and link them together for display in the sample app.

The SampleGen also handles building out the Sample Options Pane. This allows you to showcase different aspects of your component, and is done using SampleGen attributes on your sample control.

Building your first sample

Samples should contain minimal code and be easy to follow, with each sample demonstrating a common use case of the control.

Keep it minimal. Sample source code is shown in the gallery. If you have a lot of features, consider breaking them into separate samples.

To build a sample:

  1. In the samples project for your component, create a new Page or UserControl for each sample you want to add.
  2. In the backing code for the sample, add a ToolkitSample attribute to the class, like so:
[ToolkitSample(id: nameof(MyComponentSample), "MyComponent", description: $"A sample for showing how to create and use {nameof(MyComponent)}.")]
public sealed partial class MyComponentSample : Page
{
    public MyComponentSample()
    {
        this.InitializeComponent();
    }
}

That's it! The SampleGen will automatically find your sample and display it in the sample gallery app.

Take note of the id parameter in the ToolkitSample attribute. This is the unique identifier for your sample, and is used to link your sample to the sample options pane and documentation.

Add a Sample Options Pane

The Sample Options Pane is a "control pane" shown alongside your sample, and allows users to change properties of your component without cluttering the sample itself.

There are two ways to add options to the pane. One is quick and easy but is limited to a subset of controls, and one slightly more involved but more flexible.

1. Auto-generated options pane

By declaring these attributes and binding to the generated property, the SampleGen will automatically generate an interactive options pane for you.

This is the quickest way to add options to your sample, but is limited to a subset of controls.

For example:

// Number entry
[ToolkitSampleNumericOption("Minimum", 0, 0, 100, 1, false)]
[ToolkitSampleNumericOption("Maximum", 100, 0, 100, 1, false)]

// Text entry
[ToolkitSampleTextOption("SomeText", placeholderText: "Enter text")]

// Boolean option, like a switch or checkbox.
[ToolkitSampleBoolOption("Enable", true, Title = "IsEnabled")]

// Multiple choice option
[ToolkitSampleMultiChoiceOption("SelectionMode", "Single", "Multiple")]
[ToolkitSampleMultiChoiceOption("LayoutOrientation", "Horizontal", "Vertical", Title = "Orientation")]

/// Multiple choice with custom labels for each value
[ToolkitSampleMultiChoiceOption("TextForeground", "Teal : #0ddc8c", "Sand : #e7a676", "Dull green : #5d7577", Title = "Text foreground")]

[ToolkitSample(id: nameof(MyComponentSample), "MyComponent", description: $"A sample for showing how to create and use {nameof(MyComponent)}.")]
public sealed partial class MyComponentSample : Page
{
    public MyComponentSample()
    {
        this.InitializeComponent();
    }
}

Now, you can simply bind to these properties in your sample's XAML, and any changes in the options pane will be reflected by the binding.

<Page x:Class="MyComponent.Samples.MyComponentSample"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:controls="using:CommunityToolkit.WinUI.Controls">

    <Grid>
        <controls:MyComponent x:Name="MyComponent"
                              IsEnabled="{x:Bind Enable, Mode=OneWay}"
                              Maximum="{x:Bind Maximum, Mode=OneWay}"
                              Minimum="{x:Bind Minimum, Mode=OneWay}"
                              Foreground="{x:Bind TextForeground, Mode=OneWay}"
                              SelectionMode="{x:Bind SelectionMode, Mode=OneWay}"
                              SomeText="{x:Bind SomeText, Mode=OneWay}" />
    </Grid>
</Page>

2. Custom options pane

Alternatively, if you find the auto-generated options pane too limiting, you can create your own custom options pane fairly easily.

The [ToolkitSampleOptionsPane] attribute can be placed on any UserControl or Page in your sample project and provided with the Id of a declared [ToolkitSample].

The SampleGen will register this control as the sample options pane for the declared sample id, and provide the sample instance itself in the constructor of your pane.

[ToolkitSampleOptionsPane(nameof(MyComponentSample))]
public sealed partial class MyComponentSampleOptions : Page
{
    public MyComponentSampleOptions(MyComponentSample sample)
    {
        this.InitializeComponent();

        // Public properties of the sample can be accessed here.
        var publicSampleProperty = sample.SomeProperty;
        
        // Adding x:FieldModifier="public" to XAML clutters the sample source shown to the user.
        // To access x:Name'd elements of the Visual Tree,
        // use the XamlNamedPropertyRelay source generator instead:
        var publicXamlElement = new MyComponentSample.XamlNamedPropertyRelay(sample).ElementName;
    }
}

[ToolkitSampleOptionsPane] supports using constructor overloads to reuse the same options pane for multiple samples. Simply add more [ToolkitSampleOptionsPane] attributes with Ids of other [ToolkitSample]s, and add a constructor signature to match.

For an example of using one options pane for multiple samples, see our EffectAnimationsSampleOptions in the Media component. This is the pane used to start/stop animations for all Effect Animation samples.

Docs and inline interactive samples

The SampleGen tooling not only handles linking samples and sample options, but also enables writing markdown where interactive samples can be embedded within your documentation directly.

  1. Add a new markdown file in the root of the samples project. This can be named anything, so long as it's unique.
  2. Fill out your markdown file according to the template. If the front matter is not filled out properly, it may not properly display in the sample gallery.

The SampleGen will automatically find your markdown file and display it in the sample gallery app.

To display an interactive sample within your markdown, use the following syntax, replacing MyComponentSample with the declared Id of your ToolkitSample:

---
title: MyComponent
author: githubaccount
description: A short summary of your component.
keywords: ProjectTemplate, Control, Layout
dev_langs:
  - csharp
category: Controls
subcategory: Layout
discussion-id: 0
issue-id: 0
icon: assets/icon.png
---

## Markdown Header

Some text.

> [!Sample MyComponentSample]

Allowed values for the Category and Subcategory fields are defined in the ToolkitSampleCategory and ToolkitSampleSubcategory enums respectively.

Restricting Samples to Specific Platforms

If your component is only available on certain platforms, your samples will be too. By default, the sample project for a component in the Community Toolkit inherits the MultiTarget values from the src project.

This process is automatic: docs and samples are only built for and displayed on supported platforms.

If you want to change the platforms that your samples run on, you can change the MultiTarget.props in the source project, or override it by creating a new one in the sample project.

For more information, see the MultiTarget docs.

About Windows Community Toolkit

Usage

Contribution

Development/Testing

Project Structure

Clone this wiki locally