-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Adding control size trigger #3867
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
Merged
14 commits merged into
CommunityToolkit:main
from
dpaulino:feature/control-width-trigger
Aug 26, 2021
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
5420874
Adding control width trigger
dpaulino 5ba4557
Merge branch 'master' of https://github.com/dpaulino/WindowsCommunity…
dpaulino 41b580a
Adding support for height
dpaulino c0f7ff3
Renamed trigger
dpaulino b31758d
Added sample page
dpaulino a582f34
Bug fix
dpaulino cdf48d0
Fixed sample bug
dpaulino e62eb8b
Improving comments
dpaulino fd8aee5
Fixing xbind in sample
dpaulino 5a523c9
Added unit test
dpaulino 738b950
Merge branch 'master' of https://github.com/dpaulino/WindowsCommunity…
dpaulino 36f46be
Added license text
dpaulino f458d51
Added unit tests
dpaulino 8eba48b
Fixed tests
dpaulino File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Triggers/ControlSizeTrigger.bind
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<Page | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
xmlns:triggers="using:Microsoft.Toolkit.Uwp.UI.Triggers" | ||
mc:Ignorable="d"> | ||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> | ||
|
||
<VisualStateManager.VisualStateGroups> | ||
<VisualStateGroup> | ||
<VisualState> | ||
<VisualState.StateTriggers> | ||
<triggers:ControlSizeTrigger | ||
TargetElement="{Binding ElementName=ParentGrid}" | ||
MinWidth="400" | ||
MaxWidth="500"/> | ||
</VisualState.StateTriggers> | ||
<VisualState.Setters> | ||
<Setter Target="ResizingText.FontSize" Value="20"/> | ||
</VisualState.Setters> | ||
</VisualState> | ||
</VisualStateGroup> | ||
</VisualStateManager.VisualStateGroups> | ||
|
||
<StackPanel VerticalAlignment="Center" Width="500"> | ||
<Grid | ||
x:Name="ParentGrid" | ||
Width="{Binding Value, ElementName=Slider, Mode=OneWay}" | ||
Height="50" | ||
Background="Blue"/> | ||
<TextBlock | ||
x:Name="ResizingText" | ||
FontSize="12" | ||
Text="Windows Community Toolkit" | ||
HorizontalAlignment="Center"/> | ||
<Slider | ||
x:Name="Slider" | ||
Minimum="0" | ||
Maximum="500" /> | ||
</StackPanel> | ||
</Grid> | ||
</Page> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
185 changes: 185 additions & 0 deletions
185
Microsoft.Toolkit.Uwp.UI/Triggers/ControlSizeTrigger.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// 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 Windows.UI.Xaml; | ||
|
||
namespace Microsoft.Toolkit.Uwp.UI.Triggers | ||
{ | ||
/// <summary> | ||
/// A conditional state trigger that functions | ||
/// based on the target control's width or height. | ||
/// </summary> | ||
public class ControlSizeTrigger : StateTriggerBase | ||
{ | ||
/// <summary> | ||
/// Gets or sets a value indicating | ||
/// whether this trigger will be active or not. | ||
/// </summary> | ||
public bool CanTrigger | ||
{ | ||
get => (bool)GetValue(CanTriggerProperty); | ||
set => SetValue(CanTriggerProperty, value); | ||
} | ||
|
||
/// <summary> | ||
/// Identifies the <see cref="CanTrigger"/> DependencyProperty. | ||
/// </summary> | ||
public static readonly DependencyProperty CanTriggerProperty = DependencyProperty.Register( | ||
nameof(CanTrigger), | ||
typeof(bool), | ||
typeof(ControlSizeTrigger), | ||
new PropertyMetadata(true, (d, e) => ((ControlSizeTrigger)d).UpdateTrigger())); | ||
|
||
/// <summary> | ||
/// Gets or sets the max width at which to trigger. | ||
/// This value is exclusive, meaning this trigger | ||
/// could be active if the value is less than MaxWidth. | ||
/// </summary> | ||
public double MaxWidth | ||
{ | ||
get => (double)GetValue(MaxWidthProperty); | ||
set => SetValue(MaxWidthProperty, value); | ||
} | ||
|
||
/// <summary> | ||
/// Identifies the <see cref="MaxWidth"/> DependencyProperty. | ||
/// </summary> | ||
public static readonly DependencyProperty MaxWidthProperty = DependencyProperty.Register( | ||
nameof(MaxWidth), | ||
typeof(double), | ||
typeof(ControlSizeTrigger), | ||
new PropertyMetadata(double.PositiveInfinity, (d, e) => ((ControlSizeTrigger)d).UpdateTrigger())); | ||
|
||
/// <summary> | ||
/// Gets or sets the min width at which to trigger. | ||
/// This value is inclusive, meaning this trigger | ||
/// could be active if the value is >= MinWidth. | ||
/// </summary> | ||
public double MinWidth | ||
{ | ||
get => (double)GetValue(MinWidthProperty); | ||
set => SetValue(MinWidthProperty, value); | ||
} | ||
|
||
/// <summary> | ||
/// Identifies the <see cref="MinWidth"/> DependencyProperty. | ||
/// </summary> | ||
public static readonly DependencyProperty MinWidthProperty = DependencyProperty.Register( | ||
nameof(MinWidth), | ||
typeof(double), | ||
typeof(ControlSizeTrigger), | ||
new PropertyMetadata(0.0, (d, e) => ((ControlSizeTrigger)d).UpdateTrigger())); | ||
|
||
/// <summary> | ||
/// Gets or sets the max height at which to trigger. | ||
/// This value is exclusive, meaning this trigger | ||
/// could be active if the value is less than MaxHeight. | ||
/// </summary> | ||
public double MaxHeight | ||
{ | ||
get => (double)GetValue(MaxHeightProperty); | ||
set => SetValue(MaxHeightProperty, value); | ||
} | ||
|
||
/// <summary> | ||
/// Identifies the <see cref="MaxHeight"/> DependencyProperty. | ||
/// </summary> | ||
public static readonly DependencyProperty MaxHeightProperty = DependencyProperty.Register( | ||
nameof(MaxHeight), | ||
typeof(double), | ||
typeof(ControlSizeTrigger), | ||
new PropertyMetadata(double.PositiveInfinity, (d, e) => ((ControlSizeTrigger)d).UpdateTrigger())); | ||
|
||
/// <summary> | ||
/// Gets or sets the min height at which to trigger. | ||
/// This value is inclusive, meaning this trigger | ||
/// could be active if the value is >= MinHeight. | ||
/// </summary> | ||
public double MinHeight | ||
{ | ||
get => (double)GetValue(MinHeightProperty); | ||
set => SetValue(MinHeightProperty, value); | ||
} | ||
|
||
/// <summary> | ||
/// Identifies the <see cref="MinHeight"/> DependencyProperty. | ||
/// </summary> | ||
public static readonly DependencyProperty MinHeightProperty = DependencyProperty.Register( | ||
nameof(MinHeight), | ||
typeof(double), | ||
typeof(ControlSizeTrigger), | ||
new PropertyMetadata(0.0, (d, e) => ((ControlSizeTrigger)d).UpdateTrigger())); | ||
|
||
/// <summary> | ||
/// Gets or sets the element whose width will observed | ||
/// for the trigger. | ||
/// </summary> | ||
public FrameworkElement TargetElement | ||
{ | ||
get => (FrameworkElement)GetValue(TargetElementProperty); | ||
set => SetValue(TargetElementProperty, value); | ||
} | ||
|
||
/// <summary> | ||
/// Identifies the <see cref="TargetElement"/> DependencyProperty. | ||
/// </summary> | ||
/// <remarks> | ||
/// Using a DependencyProperty as the backing store for TargetElement. This enables animation, styling, binding, etc. | ||
/// </remarks> | ||
public static readonly DependencyProperty TargetElementProperty = DependencyProperty.Register( | ||
nameof(TargetElement), | ||
typeof(FrameworkElement), | ||
typeof(ControlSizeTrigger), | ||
new PropertyMetadata(null, OnTargetElementPropertyChanged)); | ||
|
||
/// <summary> | ||
/// Gets a value indicating whether the trigger is active. | ||
/// </summary> | ||
public bool IsActive { get; private set; } | ||
|
||
private static void OnTargetElementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | ||
{ | ||
((ControlSizeTrigger)d).UpdateTargetElement((FrameworkElement)e.OldValue, (FrameworkElement)e.NewValue); | ||
} | ||
|
||
// Handle event to get current values | ||
private void OnTargetElementSizeChanged(object sender, SizeChangedEventArgs e) | ||
{ | ||
UpdateTrigger(); | ||
} | ||
|
||
private void UpdateTargetElement(FrameworkElement oldValue, FrameworkElement newValue) | ||
{ | ||
if (oldValue != null) | ||
{ | ||
oldValue.SizeChanged -= OnTargetElementSizeChanged; | ||
} | ||
|
||
if (newValue != null) | ||
{ | ||
newValue.SizeChanged += OnTargetElementSizeChanged; | ||
} | ||
|
||
UpdateTrigger(); | ||
} | ||
|
||
// Logic to evaluate and apply trigger value | ||
private void UpdateTrigger() | ||
{ | ||
if (TargetElement == null || !CanTrigger) | ||
{ | ||
SetActive(false); | ||
return; | ||
} | ||
|
||
bool activate = MinWidth <= TargetElement.ActualWidth && | ||
TargetElement.ActualWidth < MaxWidth && | ||
MinHeight <= TargetElement.ActualHeight && | ||
TargetElement.ActualHeight < MaxHeight; | ||
michael-hawker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
IsActive = activate; | ||
SetActive(activate); | ||
} | ||
} | ||
} |
125 changes: 125 additions & 0 deletions
125
UnitTests/UnitTests.UWP/UI/Triggers/Test_ControlSizeTrigger.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// 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 System; | ||
using Microsoft.Toolkit.Uwp; | ||
using Microsoft.Toolkit.Uwp.UI.Triggers; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using System.Threading.Tasks; | ||
using Windows.UI.Xaml.Controls; | ||
|
||
namespace UnitTests.UWP.UI.Triggers | ||
{ | ||
[TestClass] | ||
[TestCategory("Test_ControlSizeTrigger")] | ||
public class Test_ControlSizeTrigger : VisualUITestBase | ||
{ | ||
[DataTestMethod] | ||
[DataRow(450, 450, true)] | ||
[DataRow(400, 400, true)] | ||
[DataRow(500, 500, false)] | ||
[DataRow(399, 400, false)] | ||
[DataRow(400, 399, false)] | ||
public async Task ControlSizeTriggerTest(double width, double height, bool expectedResult) | ||
{ | ||
await App.DispatcherQueue.EnqueueAsync(async () => | ||
{ | ||
Grid grid = CreateGrid(width, height); | ||
await SetTestContentAsync(grid); | ||
var trigger = new ControlSizeTrigger(); | ||
|
||
trigger.TargetElement = grid; | ||
trigger.MaxHeight = 500; | ||
trigger.MinHeight = 400; | ||
trigger.MaxWidth = 500; | ||
trigger.MinWidth = 400; | ||
|
||
Assert.AreEqual(expectedResult, trigger.IsActive); | ||
dpaulino marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow(400, 400, true)] | ||
[DataRow(400, 399, false)] | ||
public async Task ControlSizeMinHeightTriggerTest(double width, double height, bool expectedResult) | ||
{ | ||
await App.DispatcherQueue.EnqueueAsync(async () => | ||
{ | ||
Grid grid = CreateGrid(width, height); | ||
await SetTestContentAsync(grid); | ||
var trigger = new ControlSizeTrigger(); | ||
|
||
trigger.TargetElement = grid; | ||
trigger.MinHeight = 400; | ||
|
||
Assert.AreEqual(expectedResult, trigger.IsActive); | ||
}); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow(399, 400, false)] | ||
[DataRow(400, 400, true)] | ||
public async Task ControlSizeMinWidthTriggerTest(double width, double height, bool expectedResult) | ||
{ | ||
await App.DispatcherQueue.EnqueueAsync(async () => | ||
{ | ||
Grid grid = CreateGrid(width, height); | ||
await SetTestContentAsync(grid); | ||
var trigger = new ControlSizeTrigger(); | ||
|
||
trigger.TargetElement = grid; | ||
trigger.MinWidth = 400; | ||
|
||
Assert.AreEqual(expectedResult, trigger.IsActive); | ||
}); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow(450, 450, false)] | ||
[DataRow(450, 449, true)] | ||
public async Task ControlSizeMaxHeightTriggerTest(double width, double height, bool expectedResult) | ||
{ | ||
await App.DispatcherQueue.EnqueueAsync(async () => | ||
{ | ||
Grid grid = CreateGrid(width, height); | ||
await SetTestContentAsync(grid); | ||
var trigger = new ControlSizeTrigger(); | ||
|
||
trigger.TargetElement = grid; | ||
trigger.MaxHeight = 450; | ||
|
||
Assert.AreEqual(expectedResult, trigger.IsActive); | ||
}); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow(450, 450, false)] | ||
[DataRow(449, 450, true)] | ||
public async Task ControlSizeMaxWidthTriggerTest(double width, double height, bool expectedResult) | ||
{ | ||
await App.DispatcherQueue.EnqueueAsync(async () => | ||
{ | ||
Grid grid = CreateGrid(width, height); | ||
await SetTestContentAsync(grid); | ||
var trigger = new ControlSizeTrigger(); | ||
|
||
trigger.TargetElement = grid; | ||
trigger.MaxWidth = 450; | ||
|
||
Assert.AreEqual(expectedResult, trigger.IsActive); | ||
}); | ||
} | ||
|
||
private Grid CreateGrid(double width, double height) | ||
{ | ||
var grid = new Grid() | ||
{ | ||
Height = height, | ||
Width = width | ||
}; | ||
|
||
return grid; | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.