Skip to content

Commit 76c947d

Browse files
Initial Commit of ContentSizer
Content Sizer Issues: - [ ] TargetControl isn't loaded yet causes problems (Expander Issue) - [ ] Size Direction needs to be more specific (only works Left/Top, not Right/Bottom) - [ ] Do we support 'Auto'? - [ ] Need to set Automation Property Name in Code-Behind - [ ] Content Initial value as binding converter to ResizeDirection?
1 parent 1e7776e commit 76c947d

File tree

13 files changed

+519
-1
lines changed

13 files changed

+519
-1
lines changed

Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@
273273
<Content Include="Icons\More.png" />
274274
<Content Include="Icons\Notifications.png" />
275275
<Content Include="Icons\Services.png" />
276+
<Content Include="SamplePages\ContentSizer\ContentSizer.png" />
276277
<Content Include="SamplePages\Animations\Effects\EffectAnimations.png">
277278
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
278279
</Content>
@@ -496,6 +497,9 @@
496497
<Content Include="SamplePages\DataGrid\DataGridCode.bind" />
497498
<Content Include="SamplePages\ViewportBehavior\ViewportBehaviorCode.bind" />
498499
<Compile Include="Common\TextBlockHyperlinkBehavior.cs" />
500+
<Compile Include="SamplePages\ContentSizer\ContentSizerPage.xaml.cs">
501+
<DependentUpon>ContentSizerPage.xaml</DependentUpon>
502+
</Compile>
499503
<Compile Include="Common\Vector3Converter.cs" />
500504
<Compile Include="SamplePages\AutoFocusBehavior\AutoFocusBehaviorPage.xaml.cs">
501505
<DependentUpon>AutoFocusBehaviorPage.xaml</DependentUpon>
@@ -607,6 +611,7 @@
607611
<Content Include="SamplePages\StaggeredLayout\StaggeredLayout.bind" />
608612
<Content Include="SamplePages\EnumValuesExtension\EnumValuesExtensionXaml.bind" />
609613
<Content Include="SamplePages\EnumValuesExtension\EnumValuesExtensionCode.bind" />
614+
<Content Include="SamplePages\ContentSizer\ContentSizer.bind" />
610615
<Content Include="SamplePages\FocusBehavior\FocusBehaviorXaml.bind" />
611616
<Content Include="SamplePages\AutoFocusBehavior\AutoFocusBehaviorXaml.bind" />
612617
<Content Include="SamplePages\ColorPicker\ColorPickerXaml.bind" />
@@ -973,6 +978,10 @@
973978
<SubType>Designer</SubType>
974979
<Generator>MSBuild:Compile</Generator>
975980
</Page>
981+
<Page Include="SamplePages\ContentSizer\ContentSizerPage.xaml">
982+
<Generator>MSBuild:Compile</Generator>
983+
<SubType>Designer</SubType>
984+
</Page>
976985
<Page Include="SamplePages\AutoFocusBehavior\AutoFocusBehaviorPage.xaml">
977986
<SubType>Designer</SubType>
978987
<Generator>MSBuild:Compile</Generator>
@@ -1565,4 +1574,4 @@
15651574
</Target>
15661575
<!-- No-op to avoid build error when packing solution from commandline -->
15671576
<Target Name="Pack" />
1568-
</Project>
1577+
</Project>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<Page
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6+
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
7+
mc:Ignorable="d">
8+
9+
<Grid x:Name="RootGrid">
10+
<!-- Just to separate our two examples -->
11+
<Grid.ColumnDefinitions>
12+
<ColumnDefinition Width="Auto"/>
13+
<ColumnDefinition/>
14+
</Grid.ColumnDefinitions>
15+
16+
<!-- Left-side 'Shelf' -->
17+
<StackPanel Orientation="Horizontal">
18+
<Border x:Name="SideContent"
19+
Background="DarkGreen"
20+
MinWidth="200"
21+
MaxWidth="600">
22+
<TextBlock HorizontalAlignment="Center"
23+
VerticalAlignment="Center">
24+
Side Content
25+
</TextBlock>
26+
</Border>
27+
<controls:ContentSizer TargetControl="{Binding ElementName=SideContent}"/>
28+
</StackPanel>
29+
30+
<!-- Bottom 'Shelf' -->
31+
<controls:Expander x:Name="TopExpander"
32+
VerticalAlignment="Top"
33+
ExpandDirection="Up"
34+
Header="This is some Shelf"
35+
HorizontalContentAlignment="Stretch"
36+
IsExpanded="True"
37+
Grid.Column="1">
38+
<Grid Height="256">
39+
<TextBlock HorizontalAlignment="Center"
40+
TextWrapping="Wrap"
41+
Text="This is the expanded content"
42+
VerticalAlignment="Center"/>
43+
<controls:ContentSizer ResizeDirection="Horizontal" Height="16"
44+
VerticalAlignment="Bottom"/>
45+
</Grid>
46+
</controls:Expander>
47+
</Grid>
48+
</Page>
850 Bytes
Loading
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.ContentSizerPage"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7+
mc:Ignorable="d">
8+
9+
<!-- Dummy for .NET Native -->
10+
<controls:ContentSizer />
11+
</Page>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Microsoft.Toolkit.Uwp.SampleApp.Models;
6+
using Windows.UI.Xaml.Controls;
7+
using Windows.UI.Xaml.Navigation;
8+
9+
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
10+
{
11+
public sealed partial class ContentSizerPage : Page
12+
{
13+
public ContentSizerPage()
14+
{
15+
InitializeComponent();
16+
}
17+
}
18+
}

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,16 @@
175175
"Icon": "/SamplePages/ScrollHeader/ScrollHeader.png",
176176
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/behaviors/HeaderBehaviors.md"
177177
},
178+
{
179+
"Name": "ContentSizer",
180+
"Type": "ContentSizerPage",
181+
"Subcategory": "Layout",
182+
"About": "ContentSizer is a general sizing control which can manipulate the size of its parent or other elements. Used as a building block for more complex UI systems.",
183+
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ContentSizer",
184+
"XamlCodeFile": "ContentSizer.bind",
185+
"Icon": "/SamplePages/ContentSizer/ContentSizer.png",
186+
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/ContentSizer.md"
187+
},
178188
{
179189
"Name": "GridSplitter",
180190
"Type": "GridSplitterPage",
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace Microsoft.Toolkit.Uwp.UI.Controls
6+
{
7+
/// <summary>
8+
/// Enum to indicate whether <see cref="ContentSizer"/> resizes Vertically or Horizontally.
9+
/// </summary>
10+
public enum ContentResizeDirection
11+
{
12+
/// <summary>
13+
/// Determines whether to resize rows or columns based on its Alignment and
14+
/// width compared to height
15+
/// </summary>
16+
Auto, // TODO: Detect?
17+
18+
/// <summary>
19+
/// Resize columns when dragging Splitter.
20+
/// </summary>
21+
Vertical,
22+
23+
/// <summary>
24+
/// Resize rows when dragging Splitter.
25+
/// </summary>
26+
Horizontal
27+
}
28+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Microsoft.Toolkit.Uwp.UI;
6+
using Windows.UI.Xaml;
7+
using Windows.UI.Xaml.Controls;
8+
using Windows.UI.Xaml.Input;
9+
10+
namespace Microsoft.Toolkit.Uwp.UI.Controls
11+
{
12+
/// <summary>
13+
/// Events for <see cref="ContentSizer"/>.
14+
/// </summary>
15+
public partial class ContentSizer
16+
{
17+
// If no values specified, setup our default behaviors.
18+
private void ContentSizer_Loaded(object sender, RoutedEventArgs e)
19+
{
20+
// Adding Grip to Grid Splitter
21+
if (Content == null)
22+
{
23+
// TODO: Make Converter to put in XAML?
24+
Content =
25+
ResizeDirection == ContentResizeDirection.Vertical ? GripperBarVertical : GripperBarHorizontal;
26+
}
27+
28+
if (TargetControl == null)
29+
{
30+
TargetControl = this.FindAscendant<FrameworkElement>();
31+
}
32+
}
33+
34+
private void ContentSizer_KeyUp(object sender, KeyRoutedEventArgs e)
35+
{
36+
if (ResizeDirection == ContentResizeDirection.Vertical)
37+
{
38+
if (e.Key == Windows.System.VirtualKey.Left)
39+
{
40+
HorizontalMove(-GripperKeyboardChange);
41+
}
42+
else if (e.Key == Windows.System.VirtualKey.Right)
43+
{
44+
HorizontalMove(GripperKeyboardChange);
45+
}
46+
}
47+
else
48+
{
49+
if (e.Key == Windows.System.VirtualKey.Up)
50+
{
51+
VerticalMove(-GripperKeyboardChange);
52+
}
53+
else if (e.Key == Windows.System.VirtualKey.Down)
54+
{
55+
VerticalMove(GripperKeyboardChange);
56+
}
57+
}
58+
}
59+
60+
/// <inheritdoc />
61+
protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e)
62+
{
63+
var horizontalChange = e.Delta.Translation.X;
64+
var verticalChange = e.Delta.Translation.Y;
65+
66+
if (ResizeDirection == ContentResizeDirection.Vertical)
67+
{
68+
if (HorizontalMove(horizontalChange))
69+
{
70+
return;
71+
}
72+
}
73+
else if (ResizeDirection == ContentResizeDirection.Horizontal)
74+
{
75+
if (VerticalMove(verticalChange))
76+
{
77+
return;
78+
}
79+
}
80+
81+
base.OnManipulationDelta(e);
82+
}
83+
84+
private bool VerticalMove(double verticalChange)
85+
{
86+
if (TargetControl == null)
87+
{
88+
return true;
89+
}
90+
91+
if (!IsValidHeight(TargetControl, verticalChange))
92+
{
93+
return true;
94+
}
95+
96+
// TODO: This only works if splitter is on top and making things grow down
97+
// Do we need our ContentResizeDirection to be 4 way? Maybe 'Auto' would check the horizontal/vertical alignment of the target???
98+
TargetControl.Height += verticalChange;
99+
100+
return false;
101+
}
102+
103+
private bool HorizontalMove(double horizontalChange)
104+
{
105+
if (TargetControl == null)
106+
{
107+
return true;
108+
}
109+
110+
if (!IsValidWidth(TargetControl, horizontalChange))
111+
{
112+
return true;
113+
}
114+
115+
// TODO: This only works if splitter is on left and making things grow right...
116+
TargetControl.Width += horizontalChange;
117+
118+
return false;
119+
}
120+
121+
private bool IsValidHeight(FrameworkElement target, double verticalChange)
122+
{
123+
var newHeight = target.ActualHeight + verticalChange;
124+
125+
var minHeight = target.MinHeight;
126+
if (newHeight < 0 || (!double.IsNaN(minHeight) && newHeight < minHeight))
127+
{
128+
return false;
129+
}
130+
131+
var maxHeight = target.MaxHeight;
132+
if (!double.IsNaN(maxHeight) && newHeight > maxHeight)
133+
{
134+
return false;
135+
}
136+
137+
if (newHeight <= ActualHeight)
138+
{
139+
return false;
140+
}
141+
142+
return true;
143+
}
144+
145+
private bool IsValidWidth(FrameworkElement target, double horizontalChange)
146+
{
147+
var newWidth = target.ActualWidth + horizontalChange;
148+
149+
var minWidth = target.MinWidth;
150+
if (newWidth < 0 || (!double.IsNaN(minWidth) && newWidth < minWidth))
151+
{
152+
return false;
153+
}
154+
155+
var maxWidth = target.MaxWidth;
156+
if (!double.IsNaN(maxWidth) && newWidth > maxWidth)
157+
{
158+
return false;
159+
}
160+
161+
if (newWidth <= ActualWidth)
162+
{
163+
return false;
164+
}
165+
166+
return true;
167+
}
168+
}
169+
}

0 commit comments

Comments
 (0)