|
| 1 | +<!-- From: https://github.com/microsoft/WindowsAppSDK/blob/main/specs/spec_template.md --> |
| 2 | + |
| 3 | +<!-- TEMPLATE |
| 4 | + Style guide: |
| 5 | + * Use second person; speak to the developer who will be learning/using this API. |
| 6 | + (For example "you use this to..." rather than "the developer uses this to...") |
| 7 | + * Use hard returns to keep the page width within ~100 columns. |
| 8 | + (Otherwise it's more difficult to leave comments in a GitHub PR.) |
| 9 | + * Talk about an API's behavior, not its implementation. |
| 10 | + (Speak to the developer using this API, not to the team implementing it.) |
| 11 | + * A picture is worth a thousand words. |
| 12 | + * An example is worth a million words. |
| 13 | + * Keep examples realistic but simple; don't add unrelated complications. |
| 14 | + (An example that passes a stream needn't show the process of launching the File-Open dialog.) |
| 15 | +--> |
| 16 | + |
| 17 | +WrapPanel |
| 18 | +=== |
| 19 | + |
| 20 | +# Background |
| 21 | + |
| 22 | +_This spec brings WrapPanel from the Windows Community Toolkit (as WPF Polyfill) to WinUI._ |
| 23 | + |
| 24 | +WrapPanel has been a staple of XAML development since its inception, originally included in WPF |
| 25 | +[WrapPanel](https://learn.microsoft.com/dotnet/desktop/wpf/controls/wrappanel). It was originally added |
| 26 | +to the Windows Community Toolkit (WCT) in v1.3 on 2/10/2017 |
| 27 | +([see WCT history here](https://github.com/CommunityToolkit/Windows/discussions/722)) and used in a |
| 28 | +multitude of applications since. |
| 29 | + |
| 30 | +`WrapPanel` is a simple and versatile panel that positions child controls vertically or horizontally |
| 31 | +based on the orientation in sequence and when max width / max height is reached a new virtual row (in |
| 32 | +case of horizontal) or column (in case of vertical) is automatically created to fit new controls. |
| 33 | + |
| 34 | +This differs importantly from `StackPanel` where all children must be in a single row/column and aids in |
| 35 | +responsive UI flow. |
| 36 | + |
| 37 | +> [!IMPORTANT] |
| 38 | +> About WPF Compatibility: This spec aligns to the WCT implementation for compatibility for existing |
| 39 | +WinUI users. WrapPanel in the WCT was modernized and updated as part of general Panel modernization for |
| 40 | +responsive layouts done for UWP and simplified for developer's ease-of-use. It is the goal to bring this |
| 41 | +to WinUI for this same fundamental experience and allow easy migration from WCT developers and existing |
| 42 | +usage in WinUI apps vs. direct migration for WPF developers. |
| 43 | + |
| 44 | +Reference Docs: |
| 45 | +- [WCT WrapPanel Conceptual](https://learn.microsoft.com/dotnet/communitytoolkit/windows/primitives/wrappanel) |
| 46 | +- [WCT WrapPanel API](https://learn.microsoft.com/dotnet/api/communitytoolkit.winui.controls.wrappanel) |
| 47 | +- [WinUI StackPanel Conceptual](https://learn.microsoft.com/windows/apps/design/layout/layout-panels#stackpanel) |
| 48 | +- [WinUI StackPanel API Comparison](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.stackpanel) |
| 49 | +- [WPF WrapPanel Conceptual](https://learn.microsoft.com/dotnet/desktop/wpf/controls/wrappanel) |
| 50 | +- [WPF WrapPanel API](https://learn.microsoft.com/dotnet/api/system.windows.controls.wrappanel) |
| 51 | +- [WPF StackPanel API Comparison](https://learn.microsoft.com/dotnet/api/system.windows.controls.stackpanel) |
| 52 | + |
| 53 | + |
| 54 | +# Conceptual pages (How To) |
| 55 | + |
| 56 | +<!-- _(This is conceptual documentation that will go to docs.microsoft.com "how to" page)_ --> |
| 57 | + |
| 58 | +<!-- See: https://learn.microsoft.com/windows/apps/design/layout/layout-panels --> |
| 59 | + |
| 60 | +The WrapPanel is a layout panel that arranges child elements in a sequential position from left to right, |
| 61 | +items overflowing the line will break to the next line automatically at the edge of the containing panel. |
| 62 | + |
| 63 | +You can set the `Orientation` property to specify the direction of child elements. The default |
| 64 | +orientation is **Horizontal**. |
| 65 | + |
| 66 | +The following XAML shows how to create a WrapPanel of items: |
| 67 | + |
| 68 | +```xml |
| 69 | + <WrapPanel Width="132"> |
| 70 | + <Rectangle Fill="Red" Width="44" Height="44"/> |
| 71 | + <Rectangle Fill="Blue" Width="44" Height="44"/> |
| 72 | + <Rectangle Fill="Green" Width="44" Height="44"/> |
| 73 | + <Rectangle Fill="Orange" Width="44" Height="44"/> |
| 74 | + </WrapPanel> |
| 75 | +``` |
| 76 | + |
| 77 | +The result looks like this: |
| 78 | + |
| 79 | + |
| 80 | + |
| 81 | +In a WrapPanel, if a child element's size is not set explicitly, it will be given the minimal amount |
| 82 | +of space for layout. In this example, the size of the rectangles are explicitly set, if the |
| 83 | +**Width** or **Height** were not provided, the rectangle would not appear (as it would be given a |
| 84 | +**0** size in either dimension). This is a key contrast to a standard `StackPanel` control in terms |
| 85 | +of default behavior. |
| 86 | + |
| 87 | +# API Pages |
| 88 | + |
| 89 | +<!-- _(Each of the following L2 sections correspond to a page that will be on docs.microsoft.com)_ --> |
| 90 | + |
| 91 | +## WrapPanel class |
| 92 | + |
| 93 | +The WrapPanel is a layout panel that arranges child elements in a sequential position from left to right, |
| 94 | +items overflowing the line will break to the next line automatically at the edge of the containing panel. |
| 95 | + |
| 96 | + |
| 97 | + |
| 98 | +By default, WrapPanel stacks items from left to right in the order they are declared. You can set the |
| 99 | +`Orientation` property to **Vertical** to stack items from top to bottom instead, overflowing to the |
| 100 | +right. |
| 101 | + |
| 102 | +Spacing can be automatically added between items using the `HorizontalSpacing` and `VerticalSpacing` |
| 103 | +properties. When the `Orientation` is **Horizontal**, `HorizontalSpacing` adds uniform horizontal spacing |
| 104 | +between each individual item, and `VerticalSpacing` adds uniform spacing between each row of items. |
| 105 | + |
| 106 | +When the `Orientation` is **Vertical**, `HorizontalSpacing` adds uniform spacing between each column of |
| 107 | +items, and `VerticalSpacing` adds uniform vertical spacing between individual items. |
| 108 | + |
| 109 | +## WrapPanel.HorizontalSpacing property |
| 110 | + |
| 111 | +Gets or sets a uniform Horizontal distance (in pixels) between items when Orientation is set to |
| 112 | +Horizontal, or between columns of items when Orientation is set to Vertical. |
| 113 | + |
| 114 | +In the following example, HorizontalSpacing has been added to space out items, though in this case that |
| 115 | +then wraps the Green box around to the next line due to the Width constraint on the WrapPanel: |
| 116 | + |
| 117 | +```xml |
| 118 | + <controls:WrapPanel Width="132" HorizontalSpacing="16"> |
| 119 | + <Rectangle Fill="Red" Width="44" Height="44"/> |
| 120 | + <Rectangle Fill="Blue" Width="44" Height="44"/> |
| 121 | + <Rectangle Fill="Green" Width="44" Height="44"/> |
| 122 | + <Rectangle Fill="Orange" Width="44" Height="44"/> |
| 123 | + </controls:WrapPanel> |
| 124 | +``` |
| 125 | + |
| 126 | +The result looks like this: |
| 127 | + |
| 128 | + |
| 129 | + |
| 130 | +## WrapPanel.Orientation property |
| 131 | + |
| 132 | +Gets or sets the orientation of the WrapPanel. **Horizontal** means that child controls will be added |
| 133 | +horizontally until the width of the panel is reached, then a new row is added to add new child controls. |
| 134 | +**Vertical** means that children will be added vertically until the height of the panel is reached, then |
| 135 | +a new column is added. Default is **Horizontal**. |
| 136 | + |
| 137 | +## WrapPanel.Padding property |
| 138 | + |
| 139 | +Gets or sets the distance between the border and its child object. |
| 140 | + |
| 141 | +## WrapPanel.StretchChild property |
| 142 | + |
| 143 | +Gets or sets how the last child item in the WrapPanel is laid out. When set to **Last**, the final child |
| 144 | +can stretch and be given all the rest of the available space for the row (when Orientation is |
| 145 | +**Horizontal**) or column (when Orientation is **Vertical**). Defaults to **None** where no changes to |
| 146 | +default behavior layout are provided. |
| 147 | + |
| 148 | +In the following example, the last Orange rectangle will be constrained and pushed to the 2nd row. |
| 149 | +Normally if given the same Width/Height as the others, it'd sit just below the Red rectangle to the left. |
| 150 | +Instead, we can remove it's Width and have it fill the rest of the row by setting `StretchChild` to **Last**: |
| 151 | + |
| 152 | +```xml |
| 153 | + <controls:WrapPanel Width="132" StretchChild="Last"> |
| 154 | + <Rectangle Fill="Red" Width="44" Height="44"/> |
| 155 | + <Rectangle Fill="Blue" Width="44" Height="44"/> |
| 156 | + <Rectangle Fill="Green" Width="44" Height="44"/> |
| 157 | + <Rectangle Fill="Orange" Height="44" /> |
| 158 | + </controls:WrapPanel> |
| 159 | +``` |
| 160 | + |
| 161 | +The result looks like this: |
| 162 | + |
| 163 | + |
| 164 | + |
| 165 | +## Other MyExample members |
| 166 | + |
| 167 | +| Name | Description | |
| 168 | +|-|-| |
| 169 | +| VerticalSpacing | Gets or sets a uniform Vertical distance (in pixels) between items when Orientation is set to Vertical, or between rows of items when Orientation is set to Horizontal. (defaults to 0) | |
| 170 | + |
| 171 | +# API Details |
| 172 | + |
| 173 | +```c# (but really MIDL3) |
| 174 | +namespace Microsoft.UI.Xaml.Controls |
| 175 | +{ |
| 176 | + runtimeclass WrapPanel |
| 177 | + { |
| 178 | + double HorizontalSpacing { get; set; } |
| 179 | + Orientation Orientation { get; set; } |
| 180 | + Thickness Padding { get; set; } |
| 181 | + StretchChild StretchChild { get; set; } |
| 182 | + double VerticalSpacing { get; set; } |
| 183 | + } |
| 184 | + |
| 185 | + enum StretchChild |
| 186 | + { |
| 187 | + None = 0, |
| 188 | + Last |
| 189 | + } |
| 190 | +} |
| 191 | +``` |
| 192 | + |
| 193 | +# Appendix |
| 194 | + |
| 195 | +<!-- TEMPLATE |
| 196 | + Anything else that you want to write down about implementation notes and for posterity, |
| 197 | + but that isn't necessary to understand the purpose and usage of the API. |
| 198 | +
|
| 199 | + This or the Background section are a good place to describe alternative designs |
| 200 | + and why they were rejected. |
| 201 | +--> |
0 commit comments