Skip to content

Commit b076b7e

Browse files
[SettingsControls] Bugfix for wrapping states (#252)
* Push * Code cleanup * Updating samples * Update SettingsCard.xaml * Minor cleanup * Fix initial render bug --------- Co-authored-by: Arlo Godfrey <[email protected]>
1 parent 82eb9a9 commit b076b7e

File tree

5 files changed

+88
-11
lines changed

5 files changed

+88
-11
lines changed

components/SettingsControls/samples/ClickableSettingsCardSample.xaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- 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. -->
1+
<!-- 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. -->
22
<Page x:Class="SettingsControlsExperiment.Samples.ClickableSettingsCardSample"
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -13,7 +13,10 @@
1313
Header="A clickable SettingsCard"
1414
HeaderIcon="{ui:FontIcon Glyph=&#xE799;}"
1515
IsClickEnabled="True"
16-
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}" />
16+
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}">
17+
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}"
18+
Text="This is content" />
19+
</controls:SettingsCard>
1720

1821
<controls:SettingsCard ActionIcon="{ui:FontIcon Glyph=&#xE8A7;}"
1922
ActionIconToolTip="Open in new window"

components/SettingsControls/samples/SettingsCardSample.xaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- 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. -->
1+
<!-- 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. -->
22
<Page x:Class="SettingsControlsExperiment.Samples.SettingsCardSample"
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -8,6 +8,7 @@
88
xmlns:ui="using:CommunityToolkit.WinUI"
99
mc:Ignorable="d">
1010
<StackPanel Spacing="4">
11+
1112
<controls:SettingsCard x:Name="settingsCard"
1213
Description="This is a default card, with the Header, HeaderIcon, Description and Content set."
1314
Header="This is the Header"
@@ -47,5 +48,7 @@
4748
<Button Content="This control will wrap vertically!"
4849
Style="{StaticResource AccentButtonStyle}" />
4950
</controls:SettingsCard>
51+
52+
<controls:SettingsCard Header="This is a card with a Header only" />
5053
</StackPanel>
5154
</Page>

components/SettingsControls/samples/SettingsExpanderItemsSourceSample.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- 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. -->
1+
<!-- 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. -->
22
<Page x:Class="SettingsControlsExperiment.Samples.SettingsExpanderItemsSourceSample"
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

components/SettingsControls/src/SettingsCard/SettingsCard.cs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.ComponentModel.Design;
6+
57
namespace CommunityToolkit.WinUI.Controls;
68

79
/// <summary>
@@ -13,17 +15,46 @@ namespace CommunityToolkit.WinUI.Controls;
1315
[TemplatePart(Name = HeaderPresenter, Type = typeof(ContentPresenter))]
1416
[TemplatePart(Name = DescriptionPresenter, Type = typeof(ContentPresenter))]
1517
[TemplatePart(Name = HeaderIconPresenterHolder, Type = typeof(Viewbox))]
18+
19+
[TemplateVisualState(Name = NormalState, GroupName = CommonStates)]
20+
[TemplateVisualState(Name = PointerOverState, GroupName = CommonStates)]
21+
[TemplateVisualState(Name = PressedState, GroupName = CommonStates)]
22+
[TemplateVisualState(Name = DisabledState, GroupName = CommonStates)]
23+
24+
[TemplateVisualState(Name = RightState, GroupName = ContentAlignmentStates)]
25+
[TemplateVisualState(Name = RightWrappedState, GroupName = ContentAlignmentStates)]
26+
[TemplateVisualState(Name = RightWrappedNoIconState, GroupName = ContentAlignmentStates)]
27+
[TemplateVisualState(Name = LeftState, GroupName = ContentAlignmentStates)]
28+
[TemplateVisualState(Name = VerticalState, GroupName = ContentAlignmentStates)]
29+
30+
[TemplateVisualState(Name = NoContentSpacingState, GroupName = ContentSpacingStates)]
31+
[TemplateVisualState(Name = ContentSpacingState, GroupName = ContentSpacingStates)]
32+
1633
public partial class SettingsCard : ButtonBase
1734
{
35+
internal const string CommonStates = "CommonStates";
1836
internal const string NormalState = "Normal";
1937
internal const string PointerOverState = "PointerOver";
2038
internal const string PressedState = "Pressed";
2139
internal const string DisabledState = "Disabled";
2240

41+
internal const string ContentAlignmentStates = "ContentAlignmentStates";
42+
internal const string RightState = "Right";
43+
internal const string RightWrappedState = "RightWrapped";
44+
internal const string RightWrappedNoIconState = "RightWrappedNoIcon";
45+
internal const string LeftState = "Left";
46+
internal const string VerticalState = "Vertical";
47+
48+
internal const string ContentSpacingStates = "ContentSpacingStates";
49+
internal const string NoContentSpacingState = "NoContentSpacing";
50+
internal const string ContentSpacingState = "ContentSpacing";
51+
2352
internal const string ActionIconPresenterHolder = "PART_ActionIconPresenterHolder";
2453
internal const string HeaderPresenter = "PART_HeaderPresenter";
2554
internal const string DescriptionPresenter = "PART_DescriptionPresenter";
2655
internal const string HeaderIconPresenterHolder = "PART_HeaderIconPresenterHolder";
56+
57+
2758
/// <summary>
2859
/// Creates a new instance of the <see cref="SettingsCard"/> class.
2960
/// </summary>
@@ -42,11 +73,24 @@ protected override void OnApplyTemplate()
4273
OnHeaderIconChanged();
4374
OnDescriptionChanged();
4475
OnIsClickEnabledChanged();
45-
VisualStateManager.GoToState(this, IsEnabled ? NormalState : DisabledState, true);
76+
CheckInitialVisualState();
77+
4678
RegisterAutomation();
47-
IsEnabledChanged += OnIsEnabledChanged;
79+
RegisterPropertyChangedCallback(ContentProperty, OnContentChanged);
80+
IsEnabledChanged += OnIsEnabledChanged;
4881
}
4982

83+
private void CheckInitialVisualState()
84+
{
85+
VisualStateManager.GoToState(this, IsEnabled ? NormalState : DisabledState, true);
86+
87+
if (GetTemplateChild("ContentAlignmentStates") is VisualStateGroup contentAlignmentStatesGroup)
88+
{
89+
contentAlignmentStatesGroup.CurrentStateChanged -= this.ContentAlignmentStates_Changed;
90+
CheckVerticalSpacingState(contentAlignmentStatesGroup.CurrentState);
91+
contentAlignmentStatesGroup.CurrentStateChanged += this.ContentAlignmentStates_Changed;
92+
}
93+
}
5094
private void RegisterAutomation()
5195
{
5296
if (Header is string headerString && headerString != string.Empty)
@@ -207,6 +251,7 @@ private void OnDescriptionChanged()
207251
? Visibility.Visible
208252
: Visibility.Collapsed;
209253
}
254+
210255
}
211256

212257
private void OnHeaderChanged()
@@ -217,6 +262,26 @@ private void OnHeaderChanged()
217262
? Visibility.Visible
218263
: Visibility.Collapsed;
219264
}
265+
266+
}
267+
268+
private void ContentAlignmentStates_Changed(object sender, VisualStateChangedEventArgs e)
269+
{
270+
CheckVerticalSpacingState(e.NewState);
271+
}
272+
273+
private void CheckVerticalSpacingState(VisualState s)
274+
{
275+
// On state change, checking if the Content should be wrapped (e.g. when the card is made smaller or the ContentAlignment is set to Vertical). If the Content and the Header or Description are not null, we add spacing between the Content and the Header/Description.
276+
277+
if (s != null && (s.Name == RightWrappedState || s.Name == RightWrappedNoIconState || s.Name == VerticalState) && (Content != null) && (Header != null || Description != null))
278+
{
279+
VisualStateManager.GoToState(this, ContentSpacingState, true);
280+
}
281+
else
282+
{
283+
VisualStateManager.GoToState(this, NoContentSpacingState, true);
284+
}
220285
}
221286

222287
private FrameworkElement? GetFocusedElement()

components/SettingsControls/src/SettingsCard/SettingsCard.xaml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- 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. -->
1+
<!-- 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. -->
22
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:local="using:CommunityToolkit.WinUI.Controls"
@@ -106,7 +106,7 @@
106106
<Thickness x:Key="SettingsCardHeaderIconMargin">2,0,20,0</Thickness>
107107
<Thickness x:Key="SettingsCardActionIconMargin">14,0,0,0</Thickness>
108108
<x:Double x:Key="SettingsCardActionIconMaxSize">13</x:Double>
109-
<Thickness x:Key="SettingsCardVerticalHeaderContentSpacing">0,8,0,0</Thickness>
109+
<x:Double x:Key="SettingsCardVerticalHeaderContentSpacing">8</x:Double>
110110
<x:Double x:Key="SettingsCardWrapThreshold">476</x:Double>
111111
<x:Double x:Key="SettingsCardWrapNoIconThreshold">286</x:Double>
112112

@@ -310,7 +310,6 @@
310310
<Setter Target="PART_ContentPresenter.(Grid.Column)" Value="1" />
311311
<Setter Target="PART_ContentPresenter.HorizontalAlignment" Value="Stretch" />
312312
<Setter Target="PART_ContentPresenter.HorizontalContentAlignment" Value="Left" />
313-
<Setter Target="PART_ContentPresenter.Margin" Value="{ThemeResource SettingsCardVerticalHeaderContentSpacing}" />
314313
<Setter Target="HeaderPanel.Margin" Value="0" />
315314
</VisualState.Setters>
316315
</VisualState>
@@ -327,7 +326,6 @@
327326
<Setter Target="PART_ContentPresenter.(Grid.Column)" Value="1" />
328327
<Setter Target="PART_ContentPresenter.HorizontalAlignment" Value="Stretch" />
329328
<Setter Target="PART_ContentPresenter.HorizontalContentAlignment" Value="Left" />
330-
<Setter Target="PART_ContentPresenter.Margin" Value="{ThemeResource SettingsCardVerticalHeaderContentSpacing}" />
331329
<Setter Target="HeaderPanel.Margin" Value="0" />
332330
</VisualState.Setters>
333331
</VisualState>
@@ -359,7 +357,6 @@
359357
<Setter Target="PART_ContentPresenter.(Grid.Column)" Value="1" />
360358
<Setter Target="PART_ContentPresenter.HorizontalAlignment" Value="Stretch" />
361359
<Setter Target="PART_ContentPresenter.HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource TemplatedParent}}" />
362-
<Setter Target="PART_ContentPresenter.Margin" Value="{ThemeResource SettingsCardVerticalHeaderContentSpacing}" />
363360
</VisualState.Setters>
364361
</VisualState>
365362
</VisualStateGroup>
@@ -376,6 +373,15 @@
376373
</VisualState.Setters>
377374
</VisualState>
378375
</VisualStateGroup>
376+
377+
<VisualStateGroup x:Name="ContentSpacingStates">
378+
<VisualState x:Name="NoContentSpacing" />
379+
<VisualState x:Name="ContentSpacing">
380+
<VisualState.Setters>
381+
<Setter Target="PART_RootGrid.RowSpacing" Value="{ThemeResource SettingsCardVerticalHeaderContentSpacing}" />
382+
</VisualState.Setters>
383+
</VisualState>
384+
</VisualStateGroup>
379385
</VisualStateManager.VisualStateGroups>
380386

381387
<Viewbox x:Name="PART_HeaderIconPresenterHolder"

0 commit comments

Comments
 (0)