You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For the latest info, [visit the wiki article here](https://github.com/windows-toolkit/WindowsCommunityToolkit/wiki/Sample-Development).
2
4
3
-
# How to add new samples
5
+
##How to add new samples
4
6
5
7
This document describes how to add a new sample page for a new control you want to add to the toolkit.
6
8
7
-
*DropShadowPanel*, *ImageEx*, and *ImageCache* are good examples of most of the features mentioned below.
9
+
*`DropShadowPanel`*, *`ImageEx`*, and *`ImageCache`* are good examples of most of the features mentioned below.
8
10
11
+
### 1. Add Sample page and `.bind` template
9
12
10
-
## 1. Add Sample page and .bind template
11
-
First you need to create a Xaml page in the folder /SamplePages/YourControl. This will be the logical page used to by the app to navigate to the sample and contains code.
13
+
First you need to create a XAML page in the folder `/SamplePages/YourControl`. This will be the logical page used to by the app to navigate to the sample and contains code.
12
14
13
-
If providing 'live' XAML, a .bind file is loaded and dynamically fed to the XamlReader.Load method to convert into actual controls. This changes a few things about how samples need to be written (detailed below), but allows developers to actually change the sample and see the results live.
15
+
If providing 'live' XAML, a `.bind` file is loaded and dynamically fed to the `XamlReader.Load` method to convert into actual controls. This changes a few things about how samples need to be written (detailed below), but allows developers to actually change the sample and see the results live.
14
16
15
17
This not only gives us a killer sample app, but it also means that all our samples are also self-validating. There can't be a typo in the sample text given in the sample app anymore, as otherwise the sample won't work and should be caught during testing of said sample.
16
18
19
+
### 2. Binding text
17
20
18
-
## 2. Binding text
19
-
The .bind files are templates which use @[Property Name:Type:DefaultValue:Options] syntax to allow for customized options to be presented to the user in the sample app. The user can play with the values in the property page and see results change instantly. This is accomplished by using {Binding} syntax when on the property page, but switches to the raw value when the developer goes to the XAML page.
21
+
The `.bind` files are templates which use `@[Property Name:Type:DefaultValue:Options]` syntax to allow for customized options to be presented to the user in the sample app. The user can play with the values in the property page and see results change instantly. This is accomplished by using {Binding} syntax when on the property page, but switches to the raw value when the developer goes to the XAML page.
20
22
21
23
This makes it easy for a developer to test out values for a control and then copy the XAML needed for that exact result into their app.
22
24
23
-
In order to provide a property UI and associated code, you have to define a the .bind XAML file associated with your page.
25
+
In order to provide a property UI and associated code, you have to define a `.bind` XAML file associated with your page.
You can define "interactive" values in this file. The value types can be:
41
-
* String: You want the user to provide a text. The string is built like this @[Name:**String**:Default value]
42
-
* Slider: You want the user to provide a double value. The string is built like this @[Name:**Slider**:Default value:min-max]
43
-
* DoubleSlider: Same as slider but with double values (0.01 precision)
44
-
* TimeSpan: You want the user to provide a duration. The string is built like this (all values in milliseconds) @[Name:**TimeSpan**:DefaultValue:min-max]
45
-
* Enum: You want the user to provide a enum value. The string is built like this @[Name:**Enum**:EnumType.DefaultValue]
46
-
* Brush: You want the user to select a color from a list. The string is built like this @[Name:**Brush**:Black]
47
-
* Bool: You want the user to enable or disable a property. The string is built like this @[Name:**Bool**:True]
48
-
* Thickness: You want the user to provide a Thickness. The string is built like this @[Name:**Thickness**:0,20,10,0]
42
+
You can define “interactive” values in this file. The value types can be:
43
+
44
+
*`String`: You want the user to provide a text. An equivalent syntax is `@[Name:String:Default Value]`
45
+
*`Slider`: You want the user to provide a double value. An equivalent syntax is `@[Name:Slider:DefaultValue:Min-Max]`
46
+
*`DoubleSlider`: Same as slider but with double values (0.01 precision)
47
+
*`TimeSpan`: You want the user to provide a duration. An equivalent syntax is (all values in milliseconds) `@[Name:TimeSpan:DefaultValue:Min-Max]`
48
+
*`Enum`: You want the user to provide an enum value. An equivalent syntax is `@[Name:Enum:EnumType.DefaultValue]`
49
+
*`Brush`: You want the user to select a color from a list. An equivalent syntax is `@[Name:Brush:Black]`
50
+
*`Bool`: You want the user to enable or disable a property. An equivalent syntax is `@[Name:Bool:True]`
51
+
*`Thickness`: You want the user to provide a Thickness. An equivalent syntax is `@[Name:Thickness:0,20,10,0]`
49
52
50
53
The `Property Name` can also contain spaces, but these will be removed from the property name used for accessing the value in the property bag for any binding/access, see below.
51
54
52
-
The name and options will be translated **automatically** to the following syntax when your .bind template is being used on the property page:
55
+
The name and options will be translated **automatically** to the following syntax when your `.bind` template is being used on the property page:
You can also reuse a `@[Property Name]` reference by itself again later to use the same binding/value again in the same template. This will automatically get mapped to the right place without the need to specify all the types/options again. Just set those options on your first usage.
81
86
82
-
If you happen to need a two-way binding for the generated XAML, then add an extra '@' after the property definition in the template:
87
+
If you happen to need a two-way binding for the generated XAML, then add an extra '**@**' after the property definition in the template:
83
88
84
-
```xaml
85
-
Value="@[Value:Slider:0:0-180]@"
89
+
```xml
90
+
<SliderValue="@[Value:Slider:0:0-180]@" />
86
91
```
87
92
88
-
## 3. Have a *'Shallow Copy'* of your example in the sample page
89
-
Even though the sample page content is ignored and the dynamic template injected, for the XamlReader to access some classes, a reference to the item is sometimes needed in the hosting app for it to be accessible. (I assume it's an optimization thing.)
93
+
### 3. Have a '*Shallow Copy*' of your example in the sample page
94
+
95
+
Even though the sample page content is ignored and the dynamic template injected, for the `XamlReader` to access some classes, a reference to the item is sometimes needed in the hosting app for it to be accessible. (I assume it's an optimization thing.)
90
96
91
-
Therefore, for any new control/extension, you should still have a simplified snippet of it contained in the sample page compiled/loaded by the app. You should remove names, events, and properties (unless extensions) from these so the namespace isn't accidentally polluted. If you re-use the same control, you don't have to include it twice.
97
+
Therefore, for any new control/extension, you should still have a simplified snippet of it contained in the sample page compiled/loaded by the app. You should remove names, events, and properties (unless extensions) from these, so the namespace isn't accidentally polluted. If you re-use the same control, you don't have to include it twice.
92
98
99
+
### 4. For Events/Resource Templates: Have your sample page implement the **`IXamlRendererListener`** interface
93
100
94
-
## 4. For Events/Resource Templates: Have your sample page implement the **IXamlRendererListener** interface
95
-
This gets called whenever the template gets parsed (due to loading or user modification). Here you can use the [LogicalTree](https://github.com/windows-toolkit/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI/Extensions/Tree/LogicalTree.cs) extensions to grab named controls in the template and register their events. **Check for null first** as the developer may have removed the name from the element.
101
+
This gets called whenever the template gets parsed (due to loading or user modification). Here you can use the [`LogicalTree`](https://github.com/windows-toolkit/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI/Extensions/FrameworkElement/FrameworkElementExtensions.LogicalTree.cs) extensions to grab named controls in the template and register their events. **Check for null first** as the developer may have removed the name from the element.
You'll have to register all events and grab **control.Resources** for templates from this method as the regular sample page XAML isn't used and you can't hook in an event from the dynamic XAML, it must be done via code by finding the element here.
111
+
You'll have to register all events and grab **`control.Resources`** for templates from this method as the regular sample page XAML isn't used, and you can't hook in an event from the dynamic XAML, it must be done via code by finding the element here.
106
112
113
+
### 5. For Interactive Buttons: Use **`SampleController.Current.RegisterNewCommand`**
107
114
108
-
## 5. For Interactive Buttons: Use **SampleController.Current.RegisterNewCommand**
109
-
Buttons can be added through this command and are accessible in the main panel so they can be clicked when changing properties or editing XAML. It's important instead of using buttons in your sample (as events can't be directly used, see above) to register these commands.
115
+
Buttons can be added through this command and are accessible in the main panel, so they can be clicked when changing properties or editing XAML. It's important instead of using buttons in your sample (as events can't be directly used, see above) to register these commands.
If your command adds content dynamically, try and use a style template in the `.bind` XAML that the user can modify. Then grab `resources = control.Resources;` in the *`OnXamlRendered`* event and set the element style from it:
123
132
124
-
```csharp
133
+
```cs
125
134
if (resources?.ContainsKey("ThingStyle") ==true)
126
135
{
127
136
newThing.Style=resources["ThingStyle"] asStyle;
128
137
}
129
138
```
130
139
131
-
## 6. *Optional:* If you need *extra stuff* around the sample
### 6. *Optional:* If you need *extra stuff* around the sample
133
141
142
+
Now, the sample page content in the app is ignored, but you can override that behavior by adding a `<Grid x:Name="XamlRoot"/>` element to the page. If this element is found, it will serve as the host to the dynamic `.bind` content instead. In this manner you can have a status/warning message outside the control of the developer in the XAML sample tab.
After creating your page and the binding text, you just need to reference it in the `/SamplePages/samples.json` file.
137
147
Select the category where you want your page to be listed and add the following information:
138
148
139
-
## Basic Structure
149
+
###Basic Structure
140
150
141
151
```json
142
152
[
@@ -148,7 +158,7 @@ Select the category where you want your page to be listed and add the following
148
158
"Name": "AdaptiveGridView",
149
159
"Type": "AdaptiveGridViewPage",
150
160
"About": "The AdaptiveGridView control allows to present information within a Grid View perfectly adjusting the total display available space. It reacts to changes in the layout as well as the content so it can adapt to different form factors automatically. The number and the width of items are calculated based on the screen resolution in order to fully leverage the available screen space. The property ItemsHeight define the items fixed height and the property DesiredWidth sets the minimum width for the elements to add a new column.",
For creating new icons, please follow the [Thumbnail Style Guide and templates](https://github.com/windows-toolkit/WindowsCommunityToolkit-design-assets)
163
173
164
-
## Restricting Samples to Specific API Sets
174
+
###Restricting Samples to Specific API Sets
165
175
166
176
Some features used by samples aren't available on all the OS versions that the Sample App runs on. In order to make sure a sample is valid for the host OS, add the `ApiCheck` key/value in your JSON definition.
The value is a string which is the fully-qualified type-name to check for the presence of. You can also accompany this with the `BadgeUpdateVersionRequired` which uses the string provided to show a short message on the sample information so up level implementer know the minimum version required.
169
179
170
180
```json
171
181
{
@@ -177,28 +187,31 @@ The value is a string which is the fully-qualified typename to check for the pre
Every API must be accompanied by Markdown doc in the [documentation](https://github.com/windows-toolkit/WindowsCommunityToolkit/blob/master/contributing.md#docs)[repository](https://github.com/MicrosoftDocs/WindowsCommunityToolkitDocs).
* When building and running the app in release mode, the branch will automatically be changed to **master** before loading.
203
+
* The documentation is also packaged with the sample app. If there is no network connection, or the documentation is not yet on GitHub, the sample app will use the packaged version.
204
+
* To test your documentation in the sample app while running in debug mode, the Docs repository will need to be cloned in the same folder as this repository and named **`WindowsCommunityToolkitDocs`**. For
ThevalueofCodeUrlismodified when the app is built in release mode. The branch is automatically changed to **master**. This allows you to test the link in debug while pointing to dev.
217
+
The value of `CodeUrl` is modified when the app is built in release mode. The branch is automatically changed to **master**. This allows you to test the link in debug while pointing to dev.
0 commit comments