-
Notifications
You must be signed in to change notification settings - Fork 81
WrapPanel2 Component Creation #764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
99c07b3
e53c206
be5f590
c4b9ddc
4966664
dc2844e
46703b9
62b5e20
5c8a3d8
a76e62f
379769c
4977f87
a05b71d
f02d885
7716c08
811bf3b
8ccafec
c3d5658
f3fe793
8d64ee6
d2408cb
349686c
63e1196
7478e2d
3524ee9
d44ef19
701f749
901fc13
134e71c
6af1a89
e512d6c
702b181
18328c0
d8be9f2
ba0ee31
22826af
4e8ed94
1726f3d
73abf09
f36b765
ef13bd1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| @ECHO OFF | ||
|
|
||
| powershell ..\..\tooling\ProjectHeads\GenerateSingleSampleHeads.ps1 -componentPath %CD% %* |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <!-- | ||
| WinUI 2 under UWP uses TargetFramework uap10.0.* | ||
| WinUI 3 under WinAppSdk uses TargetFramework net6.0-windows10.* | ||
| However, under Uno-powered platforms, both WinUI 2 and 3 can share the same TargetFramework. | ||
|
|
||
| MSBuild doesn't play nicely with this out of the box, so we've made it easy for you. | ||
|
|
||
| For .NET Standard packages, you can use the Nuget Package Manager in Visual Studio. | ||
| For UWP / WinAppSDK / Uno packages, place the package references here. | ||
| --> | ||
| <Project> | ||
| <!-- WinUI 2 / UWP --> | ||
| <ItemGroup Condition="'$(IsUwp)' == 'true'"> | ||
| <!-- <PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.2"/> --> | ||
| </ItemGroup> | ||
|
|
||
| <!-- WinUI 2 / Uno --> | ||
| <ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '2'"> | ||
| <!-- <PackageReference Include="Uno.Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.11"/> --> | ||
| </ItemGroup> | ||
|
|
||
| <!-- WinUI 3 / WinAppSdk --> | ||
| <ItemGroup Condition="'$(IsWinAppSdk)' == 'true'"> | ||
| <!-- <PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.2"/> --> | ||
| </ItemGroup> | ||
|
|
||
| <!-- WinUI 3 / Uno --> | ||
| <ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '3'"> | ||
| <!-- <PackageReference Include="Uno.CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.100-dev.15.g12261e2626"/> --> | ||
| </ItemGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <Project> | ||
| <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" Condition="Exists('$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))')" /> | ||
|
|
||
| <PropertyGroup> | ||
| <ToolkitComponentName>WrapPanel2</ToolkitComponentName> | ||
| </PropertyGroup> | ||
|
|
||
| <!-- Sets this up as a toolkit component's sample project --> | ||
| <Import Project="$(ToolingDirectory)\ToolkitComponent.SampleProject.props" /> | ||
| <ItemGroup> | ||
| <Compile Update="WrapPanel2BasicSample.xaml.cs"> | ||
| <DependentUpon>WrapPanel2BasicSample.xaml</DependentUpon> | ||
| </Compile> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Compile Update="WrapPanel2ProportionalSample.xaml.cs"> | ||
| <DependentUpon>WrapPanel2ProportionalSample.xaml</DependentUpon> | ||
| </Compile> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Compile Update="WrapPanel2MegaSample.xaml.cs"> | ||
| <DependentUpon>WrapPanel2MegaSample.xaml</DependentUpon> | ||
| </Compile> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Content Update="WrapPanel2BasicSample.xaml"> | ||
| <SubType>Designer</SubType> | ||
| </Content> | ||
| </ItemGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| --- | ||
| title: WrapPanel2 | ||
| author: Avid29 | ||
| description: A labs-component candidate for a new WrapPanel implementation. | ||
| keywords: WrapPanel, Control, Layout | ||
| dev_langs: | ||
| - csharp | ||
| category: Layouts | ||
| subcategory: Panel | ||
| discussion-id: 762 | ||
| issue-id: 763 | ||
| icon: assets/icon.png | ||
| --- | ||
|
|
||
| # WrapPanel2 | ||
|
|
||
| The WrapPanel2 is an advanced layout control that uses `GridLength` definitions to manage item sizing within a wrapping flow. It provides granular control over how items occupy space, particularly when using proportional (Star) sizing. | ||
|
|
||
| ## Proportional Sizing Logic | ||
|
|
||
| The behavior of items with **Star** 'LayoutLength' values depends on the panel's justification: | ||
|
|
||
| **When Stretched/Distributed:** If `ItemsJustification` is set to a distribution mode (like `SpaceBetween`) or if the panel is stretched along the orientation axis, Star-sized items proportionally occupy the available remaining space. | ||
|
|
||
| **When Aligned (Start, Center, End):** Star-sized child elements will collapse to the smallest size possible while maintaining their relative proportions and ensuring all child elements are fully visible. | ||
|
|
||
| > [!Sample WrapPanel2BasicSample] | ||
|
|
||
| ## Properties | ||
|
|
||
| ### Items Justification | ||
|
|
||
| The `ItemsJustification` property determines how items are aligned and distributed along a line. | ||
|
|
||
| #### Automatic | ||
|
|
||
| Arranges items according to the control's alignment. | ||
|
|
||
| #### Start / Center / End | ||
|
|
||
| Aligns items to the beginning, middle, or end of the line. | ||
|
|
||
| #### SpaceAround | ||
|
|
||
| Equal internal padding with half-sized padding at margins. | ||
|
|
||
| #### SpaceBetween | ||
|
|
||
| Equal spacing between items; no margin padding. | ||
|
|
||
| #### SpaceEvenly | ||
|
|
||
| Equal spacing between all items and margins. | ||
|
|
||
| ### Items Stretch | ||
|
|
||
| The `ItemsStretch` property defines how the panel fills space on lines that do not contain Star-sized definitions, or when forced to fill a fixed row length. | ||
|
|
||
| #### None | ||
|
|
||
| No additional stretching is applied to non-star items. Note that Star-sized items will still expand if the `ItemsJustification` mode triggers a stretch. | ||
|
|
||
| #### First | ||
|
|
||
| The first item in the line is stretched to occupy all remaining space. | ||
|
|
||
| #### Last | ||
|
|
||
| The last item in the line is stretched to occupy all remaining space. | ||
|
|
||
| #### Equal | ||
|
|
||
| Every item in the line is stretched to a uniform size to fill the row, regardless of their individual content size. | ||
|
|
||
| #### Proportional | ||
|
|
||
| Every item in the line is stretched proportionally based on their desired size to fill the remaining space. | ||
|
|
||
| ## Additional Samples | ||
|
|
||
| ### Adjusted Sizings Sample | ||
|
|
||
| Demonstrates a mix of Auto, Pixel, and Star lengths within a wrapping layout. | ||
|
|
||
| > [!Sample WrapPanel2MegaSample] | ||
|
|
||
| ### Proportional Sizing | ||
|
|
||
| Demonstrates how Star-sized items maintain ratios even when the panel is not set to stretch. | ||
|
|
||
| > [!Sample WrapPanel2ProportionalSample] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| <!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. --> | ||
| <Page x:Class="WrapPanel2Experiment.Samples.WrapPanel2BasicSample" | ||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
| xmlns:controls="using:CommunityToolkit.WinUI.Controls" | ||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
| xmlns:local="using:WrapPanel2Experiment.Samples" | ||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
| mc:Ignorable="d"> | ||
|
|
||
| <Page.Resources> | ||
| <Style TargetType="Border"> | ||
| <Setter Property="Background" Value="#55000000" /> | ||
| <Setter Property="BorderBrush" Value="#88000000" /> | ||
| <Setter Property="CornerRadius" Value="8" /> | ||
| <Setter Property="BorderThickness" Value="1" /> | ||
| <Setter Property="Padding" Value="8" /> | ||
| <Setter Property="HorizontalAlignment" Value="Stretch" /> | ||
| <Setter Property="VerticalAlignment" Value="Stretch" /> | ||
| </Style> | ||
| </Page.Resources> | ||
|
|
||
| <Grid MaxHeight="600" | ||
| Margin="16"> | ||
| <Grid.RowDefinitions> | ||
| <RowDefinition Height="auto" /> | ||
| <RowDefinition /> | ||
| </Grid.RowDefinitions> | ||
|
|
||
| <StackPanel Margin="8" | ||
| Orientation="Horizontal" | ||
| Spacing="8"> | ||
| <Button Click="AddItemClick" | ||
| Content="Add Item" /> | ||
| <Button Click="Add5ItemsClick" | ||
| Content="Add 5 Items" /> | ||
| <Button Click="ClearItemsClick" | ||
| Content="Clear" /> | ||
| </StackPanel> | ||
|
|
||
| <controls:WrapPanel2 x:Name="WrapPanel" | ||
| Grid.Row="1" | ||
| HorizontalAlignment="{x:Bind LayoutHorizontalAlignment, Mode=OneWay}" | ||
| VerticalAlignment="{x:Bind LayoutVerticalAlignment, Mode=OneWay}" | ||
| ItemSpacing="{x:Bind ItemSpacing, Mode=OneWay}" | ||
| ItemsJustification="{x:Bind local:WrapPanel2BasicSample.ConvertStringToItemsJustification(LayoutItemsJustification), Mode=OneWay}" | ||
| ItemsStretch="{x:Bind local:WrapPanel2BasicSample.ConvertStringToItemsStretch(LayoutItemsStretch), Mode=OneWay}" | ||
| LineSpacing="{x:Bind LineSpacing, Mode=OneWay}" | ||
| Orientation="{x:Bind local:WrapPanel2BasicSample.ConvertStringToOrientation(LayoutOrientation), Mode=OneWay}" /> | ||
| </Grid> | ||
| </Page> |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,118 @@ | ||||||||
| // Licensed to the .NET Foundation under one or more agreements. | ||||||||
| // The .NET Foundation licenses this file to you under the MIT license. | ||||||||
| // See the LICENSE file in the project root for more information. | ||||||||
|
|
||||||||
| using CommunityToolkit.WinUI.Controls; | ||||||||
|
|
||||||||
| namespace WrapPanel2Experiment.Samples; | ||||||||
|
|
||||||||
| /// <summary> | ||||||||
| /// An example sample page of a custom control inheriting from Panel. | ||||||||
| /// </summary> | ||||||||
| [ToolkitSampleMultiChoiceOption("LayoutOrientation", "Horizontal", "Vertical", Title = "Orientation")] | ||||||||
| [ToolkitSampleMultiChoiceOption("LayoutHorizontalAlignment", "Left", "Center", "Right", "Stretch", Title = "Horizontal Alignment")] | ||||||||
| [ToolkitSampleMultiChoiceOption("LayoutVerticalAlignment", "Top", "Center", "Bottom", "Stretch", Title = "Vertical Alignment")] | ||||||||
| [ToolkitSampleNumericOption("ItemSpacing", 8, 0, 16, Title = "Item Spacing")] | ||||||||
| [ToolkitSampleNumericOption("LineSpacing", 2, 0, 16, Title = "Line Spacing")] | ||||||||
| [ToolkitSampleMultiChoiceOption("LayoutItemsJustification", "Automatic", "Start", "Center", "End", "SpaceAround", "SpaceBetween", "SpaceEvenly", Title = "Items Justification")] | ||||||||
| [ToolkitSampleMultiChoiceOption("LayoutItemsStretch", "None", "First", "Last", "Equal", "Proportional", Title = "Items Stretch")] | ||||||||
|
|
||||||||
| [ToolkitSample(id: nameof(WrapPanel2BasicSample), $"Basic demo of the {nameof(WrapPanel2)} with auto-sized items.", description: $"A sample showing every property of the {nameof(WrapPanel2)} panel.")] | ||||||||
| public sealed partial class WrapPanel2BasicSample : Page | ||||||||
| { | ||||||||
| public WrapPanel2BasicSample() | ||||||||
| { | ||||||||
| this.InitializeComponent(); | ||||||||
| } | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should start with some items in the collection by default, I was very confused about the properties not doing anything at first, not realizing the buttons were control buttons and not part of the collection. We actually need to just make these action buttons consistent with a little docked status bar or something in the sample infrastructure, it's been on the backlog for a while, maybe I'll take a quick look into: CommunityToolkit/Tooling-Windows-Submodule#4
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Should we just call the method for now in the constructor to have something? |
||||||||
|
|
||||||||
| // TODO: See https://github.com/CommunityToolkit/Labs-Windows/issues/149 | ||||||||
| public static Orientation ConvertStringToOrientation(string orientation) => orientation switch | ||||||||
| { | ||||||||
| "Vertical" => Orientation.Vertical, | ||||||||
| "Horizontal" => Orientation.Horizontal, | ||||||||
| _ => throw new System.NotImplementedException(), | ||||||||
| }; | ||||||||
|
|
||||||||
| // TODO: See https://github.com/CommunityToolkit/Labs-Windows/issues/149 | ||||||||
| public static HorizontalAlignment ConvertStringToHorizontalAlignment(string alignment) => alignment switch | ||||||||
| { | ||||||||
| "Left" => HorizontalAlignment.Left, | ||||||||
| "Center" => HorizontalAlignment.Center, | ||||||||
| "Right" => HorizontalAlignment.Right, | ||||||||
| "Stretch" => HorizontalAlignment.Stretch, | ||||||||
| _ => throw new System.NotImplementedException(), | ||||||||
| }; | ||||||||
|
|
||||||||
| // TODO: See https://github.com/CommunityToolkit/Labs-Windows/issues/149 | ||||||||
| public static VerticalAlignment ConvertStringToVerticalAlignment(string alignment) => alignment switch | ||||||||
| { | ||||||||
| "Top" => VerticalAlignment.Top, | ||||||||
| "Center" => VerticalAlignment.Center, | ||||||||
| "Bottom" => VerticalAlignment.Bottom, | ||||||||
| "Stretch" => VerticalAlignment.Stretch, | ||||||||
| _ => throw new System.NotImplementedException(), | ||||||||
| }; | ||||||||
|
|
||||||||
| // TODO: See https://github.com/CommunityToolkit/Labs-Windows/issues/149 | ||||||||
| public static WrapPanelItemsJustification ConvertStringToItemsJustification(string itemsJustification) => itemsJustification switch | ||||||||
| { | ||||||||
| "Automatic" => WrapPanelItemsJustification.Automatic, | ||||||||
| "Start" => WrapPanelItemsJustification.Start, | ||||||||
| "Center" => WrapPanelItemsJustification.Center, | ||||||||
| "End" => WrapPanelItemsJustification.End, | ||||||||
| "SpaceAround" => WrapPanelItemsJustification.SpaceAround, | ||||||||
| "SpaceBetween" => WrapPanelItemsJustification.SpaceBetween, | ||||||||
| "SpaceEvenly" => WrapPanelItemsJustification.SpaceEvenly, | ||||||||
| _ => throw new System.NotImplementedException(), | ||||||||
| }; | ||||||||
|
|
||||||||
| // TODO: See https://github.com/CommunityToolkit/Labs-Windows/issues/149 | ||||||||
| public static WrapPanelItemsStretch ConvertStringToItemsStretch(string stretchMethod) => stretchMethod switch | ||||||||
| { | ||||||||
| "None" => WrapPanelItemsStretch.None, | ||||||||
| "First" => WrapPanelItemsStretch.First, | ||||||||
| "Last" => WrapPanelItemsStretch.Last, | ||||||||
| "Equal" => WrapPanelItemsStretch.Equal, | ||||||||
| "Proportional" => WrapPanelItemsStretch.Proportional, | ||||||||
| _ => throw new System.NotImplementedException(), | ||||||||
| }; | ||||||||
|
|
||||||||
| private int _index; | ||||||||
|
|
||||||||
| private string[] LoremIpsumWords => LoremIpsum.Split(' '); | ||||||||
|
|
||||||||
| private string LoremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam fermentum placerat pretium. Phasellus molestie faucibus purus ut semper. Etiam felis ante, condimentum sed leo in, aliquam pharetra libero. Etiam ante ante, sagittis in semper eu, aliquam non sapien. Donec a pharetra magna. Suspendisse et nulla magna. Cras varius sem dolor, ac faucibus turpis malesuada ac. Maecenas rutrum tortor et faucibus rutrum. Vestibulum in gravida odio, non dapibus dui. Praesent leo tellus, vulputate sed sollicitudin id, fringilla quis ligula. Cras eget ex vitae purus pulvinar mattis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Donec consectetur tellus id augue ultrices, eget congue tellus pharetra."; | ||||||||
|
|
||||||||
| private void AddItemClick(object sender, RoutedEventArgs e) | ||||||||
| { | ||||||||
| AddItem(); | ||||||||
| } | ||||||||
|
|
||||||||
| private void Add5ItemsClick(object sender, RoutedEventArgs e) | ||||||||
| { | ||||||||
| for (int i = 0; i < 5; i++) | ||||||||
| AddItem(); | ||||||||
| } | ||||||||
|
|
||||||||
| private void ClearItemsClick(object sender, RoutedEventArgs e) | ||||||||
| { | ||||||||
| WrapPanel.Children.Clear(); | ||||||||
| _index = 0; | ||||||||
| } | ||||||||
|
|
||||||||
| private void AddItem() | ||||||||
| { | ||||||||
| _index = _index % LoremIpsumWords.Length; | ||||||||
|
|
||||||||
| var currentWord = LoremIpsumWords[_index++]; | ||||||||
| var border = new Border() | ||||||||
| { | ||||||||
| Child = new TextBlock() | ||||||||
| { | ||||||||
| Text = currentWord, | ||||||||
| } | ||||||||
| }; | ||||||||
|
|
||||||||
| WrapPanel.Children.Add(border); | ||||||||
| } | ||||||||
| } | ||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be good to add more here about how this extends/differs from the original WrapPanel.
(We should decide if one of our goals is drop-in upgrade or not, but that can come later.)