Merge branch 'master' into winui

This commit is contained in:
Alexandre Zollinger Chohfi 2021-01-08 16:29:38 -08:00
Родитель 2d8d53a8fe 5fe63f453c
Коммит 00de10cfe0
85 изменённых файлов: 842 добавлений и 438 удалений

9
.github/ISSUE_TEMPLATE/feature_request.md поставляемый
Просмотреть файл

@ -11,13 +11,18 @@ assignees: ''
## Describe the problem this feature would solve
<!-- Please describe or link to any existing issues or discussions.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
A clear and concise description of what the problem is, starting with the user story.
Provide examples of the restrictions in the current environment that hinders the work your users or you want to perform. What are the ways this new feature will help transform and deliver those results?
For example, I am currently using the InfiniteCanvas control which lacks the ribbon control feature. I am looking to improve user experience therefore i would like to use that in my project to provide ease of accessibility and a user-friendly interface. This new feature will provide quick access to the toolbar, enhance space utilization, etc [...] -->
## Describe the solution
<!-- A clear and concise description of what you want to happen. -->
<!-- A clear and concise description of what you want to happen. Define how do you think it will help the community and adds value to the toolkit? -->
## Describe alternatives you've considered
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
## Additional context & Screenshots
<!-- Add any other context or screenshots about the feature request here.-->

1
.github/PULL_REQUEST_TEMPLATE.md поставляемый
Просмотреть файл

@ -38,6 +38,7 @@ Please check if your PR fulfills the following requirements:
- [ ] Pull Request has been submitted to the documentation repository [instructions](..\contributing.md#docs). Link: <!-- docs PR link -->
- [ ] Sample in sample app has been added / updated (for bug fixes / features)
- [ ] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/windows-toolkit/WindowsCommunityToolkit-design-assets)
- [ ] New major technical changes in the toolkit have or will be added to the [Wiki](https://github.com/windows-toolkit/WindowsCommunityToolkit/wiki) e.g. build changes, source generators, testing infrastructure, sample creation changes, etc...
- [ ] Tests for the changes have been added (for bug fixes / features) (if applicable)
- [ ] Header has been added to all new source files (run *build/UpdateHeaders.bat*)
- [ ] Contains **NO** breaking changes

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<Title>Windows Community Toolkit Devices</Title>
<Description>This library enables easier consumption of connectivity Devices/Peripherals and handle its connection to Windows devices. It contains BluetoothLE and Network connectivity helpers.</Description>
<PackageTags>UWP Toolkit Windows Devices Bluetooth BluetoothLE BLE Networking</PackageTags>

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.DeveloperTools
/// <summary>
/// AlignmentGrid is used to display a grid to help aligning controls
/// </summary>
public class AlignmentGrid : ContentControl
public partial class AlignmentGrid : ContentControl
{
/// <summary>
/// Identifies the <see cref="LineBrush"/> dependency property.

Просмотреть файл

@ -24,7 +24,7 @@ namespace Microsoft.Toolkit.Uwp.DeveloperTools
[TemplatePart(Name = "ControlType", Type = typeof(TextBlock))]
[TemplatePart(Name = "ControlAutomationName", Type = typeof(TextBlock))]
[TemplatePart(Name = "ControlFirstParentWithName", Type = typeof(TextBlock))]
public class FocusTracker : Control
public partial class FocusTracker : Control
{
/// <summary>
/// Defines the <see cref="IsActive"/> dependency property.

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<Title>Windows Community Toolkit Developer Tools</Title>
<Description>This library provides XAML user controls and services to help developers build their app. It is part of the Windows Community Toolkit.

Просмотреть файл

@ -158,6 +158,8 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
public string ApiCheck { get; set; }
public bool HasType => !string.IsNullOrWhiteSpace(Type);
public bool HasXAMLCode => !string.IsNullOrEmpty(XamlCodeFile);
public bool HasCSharpCode => !string.IsNullOrEmpty(CodeFile);

Просмотреть файл

@ -197,7 +197,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
if (CurrentSample != null)
{
if (!string.IsNullOrWhiteSpace(CurrentSample.Type))
if (CurrentSample.HasType)
{
try
{
@ -225,7 +225,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
SamplePage.Loaded += SamplePage_Loaded;
}
}
else
else if (!CurrentSample.HasXAMLCode)
{
_onlyDocumentation = true;
}
@ -333,7 +333,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
{
base.OnNavigatedFrom(e);
if (SamplePage != null)
if (SamplePage != null && CurrentSample.HasType)
{
MethodInfo method = CurrentSample.PageType.GetMethod(
"OnNavigatedFrom",
@ -516,13 +516,13 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
if (element != null)
{
// Add element to main panel
if (SamplePage == null)
{
return;
}
// Add element to main panel or sub-panel
FrameworkElement root = null;
var root = SamplePage.FindDescendantByName("XamlRoot");
if (CurrentSample.HasType)
{
root = SamplePage?.FindDescendantByName("XamlRoot");
}
if (root is Panel)
{
@ -533,7 +533,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
else
{
// Otherwise, just replace the entire page's content
SamplePage.Content = element;
SampleContent.Content = element;
}
// Tell the page we've finished with an update to the XAML contents, after the control has rendered.

Просмотреть файл

@ -1,15 +0,0 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.CompareStateTriggerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<!-- Dummy Resource for Optimization Protection -->
<triggers:CompareStateTrigger x:Key="CompareStateTrigger"/>
</Page.Resources>
</Page>

Просмотреть файл

@ -1,24 +0,0 @@
// 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 Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class CompareStateTriggerPage : Page
{
/// <summary>
/// Initializes a new instance of the <see cref="CompareStateTriggerPage"/> class.
/// </summary>
public CompareStateTriggerPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -1,15 +0,0 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.IsEqualStateTriggerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<!-- Dummy Resource for Optimization Protection -->
<triggers:IsEqualStateTrigger x:Key="IsEqualStateTrigger"/>
</Page.Resources>
</Page>

Просмотреть файл

@ -1,24 +0,0 @@
// 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 Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class IsEqualStateTriggerPage : Page
{
/// <summary>
/// Initializes a new instance of the <see cref="IsEqualStateTriggerPage"/> class.
/// </summary>
public IsEqualStateTriggerPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -1,15 +0,0 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.IsNotEqualStateTriggerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<!-- Dummy Resource for Optimization Protection -->
<triggers:IsNotEqualStateTrigger x:Key="IsNotEqualStateTrigger"/>
</Page.Resources>
</Page>

Просмотреть файл

@ -1,24 +0,0 @@
// 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 Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class IsNotEqualStateTriggerPage : Page
{
/// <summary>
/// Initializes a new instance of the <see cref="IsNotEqualStateTriggerPage"/> class.
/// </summary>
public IsNotEqualStateTriggerPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -1,15 +1,14 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.IsNullOrEmptyStateTriggerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.IsNullOrEmptyStateTriggerPage"
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:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:triggers="using:Microsoft.Toolkit.Uwp.UI.Triggers"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Page.Resources>
<!-- Dummy Resource for Optimization Protection -->
<triggers:IsNullOrEmptyStateTrigger x:Key="IsNullOrEmptyStateTrigger"/>
<!-- Dummy Resource for Optimization Protection -->
<triggers:IsNullOrEmptyStateTrigger x:Key="IsNullOrEmptyStateTrigger" />
</Page.Resources>
</Page>

Просмотреть файл

@ -1,15 +0,0 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.NetworkConnectionStateTriggerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<!-- Dummy Resource for Optimization Protection -->
<triggers:NetworkConnectionStateTrigger x:Key="NetworkConnectionStateTrigger"/>
</Page.Resources>
</Page>

Просмотреть файл

@ -1,24 +0,0 @@
// 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 Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class NetworkConnectionStateTriggerPage : Page
{
/// <summary>
/// Initializes a new instance of the <see cref="NetworkConnectionStateTriggerPage"/> class.
/// </summary>
public NetworkConnectionStateTriggerPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -1,15 +0,0 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.UserHandPreferenceStateTriggerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<!-- Dummy Resource for Optimization Protection -->
<triggers:UserHandPreferenceStateTrigger x:Key="UserHandPreferenceStateTrigger"/>
</Page.Resources>
</Page>

Просмотреть файл

@ -1,24 +0,0 @@
// 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 Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class UserHandPreferenceStateTriggerPage : Page
{
/// <summary>
/// Initializes a new instance of the <see cref="UserHandPreferenceStateTriggerPage"/> class.
/// </summary>
public UserHandPreferenceStateTriggerPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -1,15 +0,0 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.UserInteractionModeStateTriggerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<!-- Dummy Resource for Optimization Protection -->
<triggers:UserInteractionModeStateTrigger x:Key="UserInteractionModeStateTrigger"/>
</Page.Resources>
</Page>

Просмотреть файл

@ -1,24 +0,0 @@
// 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 Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class UserInteractionModeStateTriggerPage : Page
{
/// <summary>
/// Initializes a new instance of the <see cref="UserInteractionModeStateTriggerPage"/> class.
/// </summary>
public UserInteractionModeStateTriggerPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.XamlOnlyPage"
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:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:triggers="using:Microsoft.Toolkit.Uwp.UI.Triggers"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<!-- Dummy Page for .NET Native Optimization Protection -->
<!-- Put a copy of any controls/resources required for XAML Parsing within XAML Only Samples -->
<!-- This page is never loaded by the app, but used to trick the compiler... -->
<Page.Resources>
<triggers:CompareStateTrigger x:Key="CompareStateTrigger" />
<triggers:IsEqualStateTrigger x:Key="IsEqualStateTrigger" />
<triggers:IsNotEqualStateTrigger x:Key="IsNotEqualStateTrigger" />
<triggers:NetworkConnectionStateTrigger x:Key="NetworkConnectionStateTrigger" />
<triggers:RegexStateTrigger x:Key="RegexStateTrigger" />
<triggers:UserHandPreferenceStateTrigger x:Key="UserHandPreferenceStateTrigger" />
<triggers:UserInteractionModeStateTrigger x:Key="UserInteractionModeStateTrigger" />
</Page.Resources>
<Grid />
</Page>

Просмотреть файл

@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
@ -11,14 +9,12 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class RegexStateTriggerPage : Page
public sealed partial class XamlOnlyPage : Page
{
/// <summary>
/// Initializes a new instance of the <see cref="RegexStateTriggerPage"/> class.
/// </summary>
public RegexStateTriggerPage()
public XamlOnlyPage()
{
InitializeComponent();
// DO NOT add any code here, this page is never loaded...
this.InitializeComponent();
}
}
}

Просмотреть файл

@ -928,7 +928,6 @@
},
{
"Name": "CompareStateTrigger",
"Type": "CompareStateTriggerPage",
"Subcategory": "State Triggers",
"About": "Enables a state if the value is equal to, greater than, or less than another value",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Triggers",
@ -938,7 +937,6 @@
},
{
"Name": "IsEqualStateTrigger",
"Type": "IsEqualStateTriggerPage",
"Subcategory": "State Triggers",
"About": "Enables a state if the value is equal to another value",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Triggers",
@ -968,7 +966,6 @@
},
{
"Name": "NetworkConnectionStateTrigger",
"Type": "NetworkConnectionStateTriggerPage",
"Subcategory": "State Triggers",
"About": "Trigger for switching when the network availability changes",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Triggers",
@ -978,7 +975,6 @@
},
{
"Name": "IsNotEqualStateTrigger",
"Type": "IsNotEqualStateTriggerPage",
"Subcategory": "State Triggers",
"About": "Enables a state if the value is not equal to another value",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Triggers",
@ -988,7 +984,6 @@
},
{
"Name": "RegexStateTrigger",
"Type": "RegexStateTriggerPage",
"Subcategory": "State Triggers",
"About": "Enables a state if the regex expression is true for a given string value",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Triggers",
@ -998,7 +993,6 @@
},
{
"Name": "UserHandPreferenceStateTrigger",
"Type": "UserHandPreferenceStateTriggerPage",
"Subcategory": "State Triggers",
"About": "Trigger for switching UI based on whether the user favours their left or right hand.",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Triggers",
@ -1008,7 +1002,6 @@
},
{
"Name": "UserInteractionModeStateTrigger",
"Type": "UserInteractionModeStateTriggerPage",
"Subcategory": "State Triggers",
"About": "Trigger for switching when the User interaction mode changes (tablet mode)",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Triggers",

Просмотреть файл

@ -14,7 +14,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// Abstract class providing common dependency properties for composition animations
/// </summary>
[ContentProperty(Name = nameof(KeyFrames))]
public abstract class AnimationBase : DependencyObject
public abstract partial class AnimationBase : DependencyObject
{
/// <summary>
/// Identifies the <see cref="Target"/> property

Просмотреть файл

@ -9,7 +9,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <summary>
/// Provides common Dependency properties for KeyFrames
/// </summary>
public abstract class KeyFrame : DependencyObject
public abstract partial class KeyFrame : DependencyObject
{
/// <summary>
/// Identifies the <see cref="Key"/> dependency property

Просмотреть файл

@ -9,7 +9,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <summary>
/// Internal tool to link composite transforms to elements
/// </summary>
internal class AnimationTools : DependencyObject
internal partial class AnimationTools : DependencyObject
{
/// <summary>
/// Attached property used to link composite transform with UIElement

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<Title>Windows Community Toolkit Animations</Title>
<Description>
This library provides helpers and extensions on top of Windows Composition and XAML storyboards. It is part of the Windows Community Toolkit.

Просмотреть файл

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<Title>Windows Community Toolkit Controls DataGrid</Title>
<Description>
This library provides a XAML DataGrid control. It is part of the Windows Community Toolkit.

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<Title>Windows Community Toolkit Layout</Title>
<Description>
This library provides XAML layout controls. It is part of the Windows Community Toolkit.

Просмотреть файл

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<Title>Windows Community Toolkit Controls Markdown</Title>
<Description>
This library provides a XAML MarkdownTextBlock control, an efficient and extensible control that can parse and render markdown. It is part of the Windows Community Toolkit.

Просмотреть файл

@ -39,6 +39,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// </summary>
public static readonly DependencyProperty CloseButtonForegroundProperty = DependencyProperty.Register(nameof(CloseButtonForeground), typeof(Brush), typeof(BladeItem), new PropertyMetadata(new SolidColorBrush(Colors.Black)));
private WeakReference<BladeView> _parentBladeView;
/// <summary>
/// Gets or sets the foreground color of the close button
/// </summary>
@ -84,6 +86,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
set { SetValue(IsOpenProperty, value); }
}
internal BladeView ParentBladeView
{
get
{
this._parentBladeView.TryGetTarget(out var bladeView);
return bladeView;
}
set => this._parentBladeView = new WeakReference<BladeView>(value);
}
private static void IsOpenChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
BladeItem bladeItem = (BladeItem)dependencyObject;

Просмотреть файл

@ -4,8 +4,10 @@
using System;
using Microsoft.Toolkit.Uwp.Extensions;
using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.UI.Controls
@ -92,6 +94,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
}
}
/// <summary>
/// Creates AutomationPeer (<see cref="UIElement.OnCreateAutomationPeer"/>)
/// </summary>
/// <returns>An automation peer for this <see cref="BladeItem"/>.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
return new BladeItemAutomationPeer(this);
}
private void OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
{
if (IsExpanded)

Просмотреть файл

@ -0,0 +1,163 @@
// 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 Microsoft.Toolkit.Uwp.UI.Controls;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.UI.Automation.Peers
{
/// <summary>
/// Defines a framework element automation peer for the <see cref="BladeItem"/>.
/// </summary>
public class BladeItemAutomationPeer : FrameworkElementAutomationPeer
{
/// <summary>
/// Initializes a new instance of the <see cref="BladeItemAutomationPeer"/> class.
/// </summary>
/// <param name="owner">
/// The <see cref="BladeItem" /> that is associated with this <see cref="T:Windows.UI.Xaml.Automation.Peers.BladeItemAutomationPeer" />.
/// </param>
public BladeItemAutomationPeer(BladeItem owner)
: base(owner)
{
}
private BladeItem OwnerBladeItem
{
get { return this.Owner as BladeItem; }
}
/// <summary>
/// Gets the control type for the element that is associated with the UI Automation peer.
/// </summary>
/// <returns>The control type.</returns>
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.ListItem;
}
/// <summary>
/// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
/// differentiates the control represented by this AutomationPeer.
/// </summary>
/// <returns>The string that contains the name.</returns>
protected override string GetClassNameCore()
{
return Owner.GetType().Name;
}
/// <summary>
/// Called by GetName.
/// </summary>
/// <returns>
/// Returns the first of these that is not null or empty:
/// - Value returned by the base implementation
/// - Name of the owning BladeItem
/// - BladeItem class name
/// </returns>
protected override string GetNameCore()
{
string name = AutomationProperties.GetName(this.OwnerBladeItem);
if (!string.IsNullOrEmpty(name))
{
return name;
}
name = this.OwnerBladeItem.Name;
if (!string.IsNullOrEmpty(name))
{
return name;
}
name = this.OwnerBladeItem.Header?.ToString();
if (!string.IsNullOrEmpty(name))
{
return name;
}
TextBlock textBlock = this.OwnerBladeItem.FindDescendant<TextBlock>();
if (textBlock != null)
{
return textBlock.Text;
}
name = base.GetNameCore();
if (!string.IsNullOrEmpty(name))
{
return name;
}
return string.Empty;
}
/// <summary>
/// Called by GetAutomationId that gets the **AutomationId** of the element that is associated with the automation peer.
/// </summary>
/// <returns>
/// The string that contains the automation ID.
/// </returns>
protected override string GetAutomationIdCore()
{
string automationId = base.GetAutomationIdCore();
if (!string.IsNullOrEmpty(automationId))
{
return automationId;
}
if (this.OwnerBladeItem != null)
{
return this.GetNameCore();
}
return string.Empty;
}
/// <summary>
/// Returns the size of the set where the element that is associated with the automation peer is located.
/// </summary>
/// <returns>
/// The size of the set.
/// </returns>
protected override int GetSizeOfSetCore()
{
int sizeOfSet = base.GetSizeOfSetCore();
if (sizeOfSet != -1)
{
return sizeOfSet;
}
BladeItem owner = this.OwnerBladeItem;
BladeView parent = owner.ParentBladeView;
sizeOfSet = parent.Items.Count;
return sizeOfSet;
}
/// <summary>
/// Returns the ordinal position in the set for the element that is associated with the automation peer.
/// </summary>
/// <returns>
/// The ordinal position in the set.
/// </returns>
protected override int GetPositionInSetCore()
{
int positionInSet = base.GetPositionInSetCore();
if (positionInSet != -1)
{
return positionInSet;
}
BladeItem owner = this.OwnerBladeItem;
BladeView parent = owner.ParentBladeView;
positionInSet = parent.IndexFromContainer(owner);
return positionInSet;
}
}
}

Просмотреть файл

@ -5,8 +5,10 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation;
using Windows.Foundation.Collections;
@ -63,6 +65,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
if (blade != null)
{
blade.VisibilityChanged += BladeOnVisibilityChanged;
blade.ParentBladeView = this;
}
base.PrepareContainerForItemOverride(element, item);
@ -81,6 +84,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
base.ClearContainerForItemOverride(element, item);
}
/// <summary>
/// Creates AutomationPeer (<see cref="UIElement.OnCreateAutomationPeer"/>)
/// </summary>
/// <returns>An automation peer for this <see cref="BladeView"/>.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
return new BladeViewAutomationPeer(this);
}
private void CycleBlades()
{
ActiveBlades = new ObservableCollection<BladeItem>();

Просмотреть файл

@ -0,0 +1,115 @@
// 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.Collections.Generic;
using Microsoft.Toolkit.Uwp.UI.Controls;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.UI.Automation.Peers
{
/// <summary>
/// Defines a framework element automation peer for the <see cref="BladeView"/> control.
/// </summary>
public class BladeViewAutomationPeer : ItemsControlAutomationPeer
{
/// <summary>
/// Initializes a new instance of the <see cref="BladeViewAutomationPeer"/> class.
/// </summary>
/// <param name="owner">
/// The <see cref="BladeView" /> that is associated with this <see cref="T:Windows.UI.Xaml.Automation.Peers.BladeViewAutomationPeer" />.
/// </param>
public BladeViewAutomationPeer(BladeView owner)
: base(owner)
{
}
private BladeView OwningBladeView
{
get
{
return Owner as BladeView;
}
}
/// <summary>
/// Gets the control type for the element that is associated with the UI Automation peer.
/// </summary>
/// <returns>The control type.</returns>
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.List;
}
/// <summary>
/// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
/// differentiates the control represented by this AutomationPeer.
/// </summary>
/// <returns>The string that contains the name.</returns>
protected override string GetClassNameCore()
{
return Owner.GetType().Name;
}
/// <summary>
/// Called by GetName.
/// </summary>
/// <returns>
/// Returns the first of these that is not null or empty:
/// - Value returned by the base implementation
/// - Name of the owning BladeView
/// - BladeView class name
/// </returns>
protected override string GetNameCore()
{
string name = AutomationProperties.GetName(this.OwningBladeView);
if (!string.IsNullOrEmpty(name))
{
return name;
}
name = this.OwningBladeView.Name;
if (!string.IsNullOrEmpty(name))
{
return name;
}
name = base.GetNameCore();
if (!string.IsNullOrEmpty(name))
{
return name;
}
return string.Empty;
}
/// <summary>
/// Gets the collection of elements that are represented in the UI Automation tree as immediate
/// child elements of the automation peer.
/// </summary>
/// <returns>The children elements.</returns>
protected override IList<AutomationPeer> GetChildrenCore()
{
BladeView owner = OwningBladeView;
ItemCollection items = owner.Items;
if (items.Count <= 0)
{
return null;
}
List<AutomationPeer> peers = new List<AutomationPeer>(items.Count);
for (int i = 0; i < items.Count; i++)
{
if (owner.ContainerFromIndex(i) is BladeItem element)
{
peers.Add(FromElement(element) ?? CreatePeerForElement(element));
}
}
return peers;
}
}
}

Просмотреть файл

@ -20,7 +20,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// A modern UI Carousel control. Really flexible. Works with touch, keyboard, mouse.
/// </summary>
public class Carousel : ItemsControl
public partial class Carousel : ItemsControl
{
/// <summary>
/// Gets or sets the selected item.

Просмотреть файл

@ -13,7 +13,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// Represents the container for an item in a Carousel control.
/// </summary>
public class CarouselItem : SelectorItem
public partial class CarouselItem : SelectorItem
{
private const string PointerOverState = "PointerOver";
private const string PointerOverSelectedState = "PointerOverSelected";

Просмотреть файл

@ -18,7 +18,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// The panel used in the <see cref="Carousel"/> control
/// </summary>
public class CarouselPanel : Panel
public partial class CarouselPanel : Panel
{
// Storyboard on gesture
private Storyboard storyboard = new Storyboard();

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// A <see cref="DropDownButton"/> which displays a color as its <c>Content</c> and it's <c>Flyout</c> is a <see cref="ColorPicker"/>.
/// </summary>
[TemplatePart(Name = nameof(CheckeredBackgroundBorder), Type = typeof(Border))]
public class ColorPickerButton : DropDownButton
public partial class ColorPickerButton : DropDownButton
{
/// <summary>
/// Gets the <see cref="Controls.ColorPicker"/> instances contained by the <see cref="DropDownButton"/>.

Просмотреть файл

@ -10,7 +10,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// Provides the base implementation for all controls that contain single content and have a header.
/// </summary>
public class HeaderedContentControl : ContentControl
public partial class HeaderedContentControl : ContentControl
{
private const string PartHeaderPresenter = "HeaderPresenter";

Просмотреть файл

@ -10,7 +10,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// Represents a control that contains multiple items and has a header.
/// </summary>
public class HeaderedItemsControl : ItemsControl
public partial class HeaderedItemsControl : ItemsControl
{
/// <summary>
/// Initializes a new instance of the <see cref="HeaderedItemsControl"/> class.

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// Allows raise an event when the value of a dependency property changes when a view model is otherwise not necessary.
/// </summary>
/// <typeparam name="TPropertyType">Type of the DependencyProperty</typeparam>
internal class PropertyChangeEventSource<TPropertyType> : FrameworkElement
internal partial class PropertyChangeEventSource<TPropertyType> : FrameworkElement
{
private readonly DependencyObject _source;

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<Title>Windows Community Toolkit Controls</Title>
<Description>
This library provides XAML templated controls. It is part of the Windows Community Toolkit.
@ -45,6 +45,7 @@
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Text.Json" Version="4.7.2" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -25,7 +25,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
[TemplatePart(Name = "AnchorCanvas", Type = typeof(Canvas))]
[TemplatePart(Name = "OrbitGrid", Type = typeof(Grid))]
[TemplatePart(Name = "CenterContent", Type = typeof(ContentPresenter))]
public class OrbitView : ItemsControl
public partial class OrbitView : ItemsControl
{
private const double AnimationDuration = 200;
@ -631,41 +631,48 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
var anchorVisual = ElementCompositionPreview.GetElementVisual(anchor);
var elementVisual = ElementCompositionPreview.GetElementVisual(element);
var centerVisual = ElementCompositionPreview.GetElementVisual(_centerContent);
var elementNode = elementVisual.GetReference();
var centerNode = centerVisual.GetReference();
ScalarNode expression;
var elementY = elementNode.Offset.Y + (elementNode.Size.Y / 2);
var centerY = centerNode.Offset.Y + (centerNode.Size.Y / 2);
var elementX = elementNode.Offset.X + (elementNode.Size.X / 2);
var centerX = centerNode.Offset.X + (centerNode.Size.X / 2);
string expression = string.Empty;
var elementY = "(elementVisual.Offset.Y + elementVisual.Size.Y / 2)";
var centerY = "(centerVisual.Offset.Y + centerVisual.Size.Y / 2)";
var elementX = "(elementVisual.Offset.X + elementVisual.Size.X / 2)";
var centerX = "(centerVisual.Offset.X + centerVisual.Size.X / 2)";
var startingAngle = Math.Atan2(y, x);
if (startingAngle > Math.PI / 4 && startingAngle < 3 * Math.PI / 4)
{
expression = ExpressionFunctions.ATan((-1 * (elementX - centerX)) / (elementY - centerY)) - ((float)Math.PI / 2.0f);
expression = $"Atan((-1 * ({elementX} - {centerX})) / ( {elementY} - {centerY})) - PI / 2";
}
else if (startingAngle >= 3 * Math.PI / 4 || startingAngle < -3 * Math.PI / 4)
{
expression = ExpressionFunctions.ATan((elementY - centerY) / (elementX - centerX)) + (float)Math.PI;
expression = $"Atan(({elementY} - {centerY}) / ({elementX} - {centerX})) + PI";
}
else if (startingAngle >= -3 * Math.PI / 4 && startingAngle < Math.PI / -4)
{
expression = ExpressionFunctions.ATan((elementX - centerX) / (-1 * (elementY - centerY))) + ((float)Math.PI / 2.0f);
expression = $"Atan(({elementX} - {centerX}) / (-1 * ({elementY} - {centerY}))) + PI / 2";
}
else
{
expression = ExpressionFunctions.ATan((elementY - centerY) / (elementX - centerX));
expression = $"Atan(({elementY} - {centerY}) / ({elementX} - {centerX}))";
}
anchorVisual.CenterPoint = new Vector3(0);
anchorVisual.StartAnimation(nameof(anchorVisual.RotationAngle), expression);
var rotationExpression = _compositor.CreateExpressionAnimation();
rotationExpression.Expression = expression;
rotationExpression.SetReferenceParameter("centerVisual", centerVisual);
rotationExpression.SetReferenceParameter("elementVisual", elementVisual);
anchorVisual.StartAnimation(nameof(anchorVisual.RotationAngle), rotationExpression);
var offsetExpression = ExpressionFunctions.Vector3(centerNode.Offset.X + (centerNode.Size.X / 2), centerNode.Offset.Y + (centerNode.Size.Y / 2), 0);
var offsetExpression = _compositor.CreateExpressionAnimation();
offsetExpression.Expression = "Vector3(centerVisual.Offset.X + centerVisual.Size.X / 2, centerVisual.Offset.Y + centerVisual.Size.Y / 2, 0)";
offsetExpression.SetReferenceParameter("centerVisual", centerVisual);
anchorVisual.StartAnimation(nameof(anchorVisual.Offset), offsetExpression);
var scaleExpression = ExpressionFunctions.Vector3(ExpressionFunctions.Pow(ExpressionFunctions.Pow(elementX - centerX, 2) + ExpressionFunctions.Pow(elementY - centerY, 2), 0.5f) / 80, 1, 1);
var scaleExpression = _compositor.CreateExpressionAnimation();
scaleExpression.Expression = $"Vector3(Pow(Pow({elementX} - {centerX}, 2) + Pow({elementY} - {centerY}, 2), 0.5)/80, 1, 1)";
scaleExpression.SetReferenceParameter("centerVisual", centerVisual);
scaleExpression.SetReferenceParameter("elementVisual", elementVisual);
anchorVisual.StartAnimation(nameof(anchorVisual.Scale), scaleExpression);
return anchor;

Просмотреть файл

@ -11,7 +11,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// A class that can be used to provide data context for <see cref="OrbitView"></see> items by providing distance and diameter values
/// </summary>
public class OrbitViewDataItem : DependencyObject
public partial class OrbitViewDataItem : DependencyObject
{
/// <summary>
/// Gets or sets a value indicating the distance from the center.

Просмотреть файл

@ -17,7 +17,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
[TemplateVisualState(Name = VsNormal, GroupName = CommonStateGroup)]
[TemplateVisualState(Name = VsPressed, GroupName = CommonStateGroup)]
[TemplateVisualState(Name = VsPointerOver, GroupName = CommonStateGroup)]
public class OrbitViewItem : ContentControl
public partial class OrbitViewItem : ContentControl
{
private const string CommonStateGroup = "CommonStates";
private const string VsNormal = "Normal";

Просмотреть файл

@ -19,7 +19,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
[TemplatePart(Name = OutlineArcPartName, Type = typeof(ArcSegment))]
[TemplatePart(Name = BarFigurePartName, Type = typeof(PathFigure))]
[TemplatePart(Name = BarArcPartName, Type = typeof(ArcSegment))]
public class RadialProgressBar : ProgressBar
public partial class RadialProgressBar : ProgressBar
{
private const string OutlineFigurePartName = "OutlineFigurePart";
private const string OutlineArcPartName = "OutlineArcPart";

Просмотреть файл

@ -25,7 +25,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
[TemplatePart(Name = "StatusType", Type = typeof(ComboBox))]
[TemplatePart(Name = "AuthorizationType", Type = typeof(ComboBox))]
[TemplatePart(Name = "AdvancedFiltersGrid", Type = typeof(Grid))]
public sealed class RemoteDevicePicker : ContentDialog
public sealed partial class RemoteDevicePicker : ContentDialog
{
private ListView _listDevices;
private ComboBox _listDeviceTypes;

Просмотреть файл

@ -24,7 +24,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
[TemplatePart(Name = NextPartName, Type = typeof(FrameworkElement))]
[TemplatePart(Name = TranslatePartName, Type = typeof(TranslateTransform))]
[TemplatePart(Name = StackPartName, Type = typeof(StackPanel))]
public class RotatorTile : Control
public partial class RotatorTile : Control
{
private const string ScrollerPartName = "Scroller";
private const string CurrentPartName = "Current";

Просмотреть файл

@ -13,7 +13,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// Scroll header control to be used with ListViews or GridViews
/// </summary>
public class ScrollHeader : ContentControl
public partial class ScrollHeader : ContentControl
{
/// <summary>
/// Initializes a new instance of the <see cref="ScrollHeader"/> class.

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <see cref="Case"/> is the value container for the <see cref="SwitchPresenter"/>.
/// </summary>
[ContentProperty(Name = nameof(Content))]
public class Case : DependencyObject
public partial class Case : DependencyObject
{
internal SwitchPresenter Parent { get; set; } // TODO: Can we remove Parent need here and just use events?

Просмотреть файл

@ -15,7 +15,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// When provided a set of <see cref="Case"/>s and a <see cref="Value"/>, it will pick the matching <see cref="Case"/> with the corresponding <see cref="Case.Value"/>.
/// </summary>
[ContentProperty(Name = nameof(SwitchCases))]
public sealed class SwitchPresenter : ContentPresenter
public sealed partial class SwitchPresenter : ContentPresenter
{
/// <summary>
/// Gets the current <see cref="Case"/> which is being displayed.

Просмотреть файл

@ -7,7 +7,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.TextToolbarSymbols
/// <summary>
/// Creates a List Icon
/// </summary>
public class List : Symbol
public partial class List : Symbol
{
/// <summary>
/// Initializes a new instance of the <see cref="List"/> class.

Просмотреть файл

@ -7,7 +7,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.TextToolbarSymbols
/// <summary>
/// Creates a Numbered List Icon
/// </summary>
public class NumberedList : Symbol
public partial class NumberedList : Symbol
{
/// <summary>
/// Initializes a new instance of the <see cref="NumberedList"/> class.

Просмотреть файл

@ -13,7 +13,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.TextToolbarSymbols
/// </summary>
[TemplateVisualState(GroupName = Common, Name = Normal)]
[TemplateVisualState(GroupName = Common, Name = Disabled)]
public abstract class Symbol : Control
public abstract partial class Symbol : Control
{
internal const string Common = "CommonStates";
internal const string Normal = "Normal";

Просмотреть файл

@ -9,7 +9,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.TextToolbarButtons
/// <summary>
/// Specifies a DefaultButton, modifies a Button Instance
/// </summary>
public class DefaultButton : DependencyObject
public partial class DefaultButton : DependencyObject
{
/// <summary>
/// Identifies the <see cref="IsVisible"/> dependency property.

Просмотреть файл

@ -14,7 +14,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.TextToolbarButtons
/// <summary>
/// An Interactive button in the TextToolbar, to perform a formatting task.
/// </summary>
public class ToolbarButton : AppBarButton, IToolbarItem, INotifyPropertyChanged
public partial class ToolbarButton : AppBarButton, IToolbarItem, INotifyPropertyChanged
{
/// <summary>
/// Identifies the <see cref="ToolTip"/> dependency property.
@ -164,6 +164,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.TextToolbarButtons
set
{
_position = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Position)));
}
}

Просмотреть файл

@ -9,7 +9,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.TextToolbarButtons
/// <summary>
/// Separates a collection of <see cref="IToolbarItem"/>
/// </summary>
public class ToolbarSeparator : AppBarSeparator, IToolbarItem
public partial class ToolbarSeparator : AppBarSeparator, IToolbarItem
{
/// <summary>
/// Initializes a new instance of the <see cref="ToolbarSeparator"/> class.

Просмотреть файл

@ -8,7 +8,6 @@ using System.Linq;
using System.Numerics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Toolkit.Uwp.UI.Animations.Expressions;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.UI.Composition;
using Microsoft.UI.Xaml;
@ -439,11 +438,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <param name="scrollOrientation">The ScrollOrientation</param>
private void CreateModuloExpression(ScrollViewer scrollViewer, double imageWidth, double imageHeight, ScrollOrientation scrollOrientation)
{
const string offsetXParam = "offsetX";
const string offsetYParam = "offsetY";
const string imageWidthParam = "imageWidth";
const string imageHeightParam = "imageHeight";
const string speedParam = "speed";
const string propSetParam = "p";
const string offsetXParam = nameof(OffsetX);
const string qualifiedOffsetXParam = propSetParam + "." + offsetXParam;
const string offsetYParam = nameof(OffsetY);
const string qualifiedOffsetYParam = propSetParam + "." + offsetYParam;
const string imageWidthParam = nameof(imageWidth);
const string qualifiedImageWidthParam = propSetParam + "." + imageWidthParam;
const string imageHeightParam = nameof(imageHeight);
const string qualifiedImageHeightParam = propSetParam + "." + imageHeightParam;
const string speedParam = nameof(ParallaxSpeedRatio);
if (_containerVisual == null)
{
@ -453,10 +457,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
var compositor = _containerVisual.Compositor;
// Setup the expression
ExpressionNode expressionX = null;
ExpressionNode expressionY = null;
ExpressionNode expressionXVal;
ExpressionNode expressionYVal;
var expressionX = compositor.CreateExpressionAnimation();
var expressionY = compositor.CreateExpressionAnimation();
var propertySetModulo = compositor.CreatePropertySet();
propertySetModulo.InsertScalar(imageWidthParam, (float)imageWidth);
@ -465,78 +467,67 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
propertySetModulo.InsertScalar(offsetYParam, (float)OffsetY);
propertySetModulo.InsertScalar(speedParam, (float)ParallaxSpeedRatio);
var propertySetNodeModulo = propertySetModulo.GetReference();
expressionX.SetReferenceParameter(propSetParam, propertySetModulo);
expressionY.SetReferenceParameter(propSetParam, propertySetModulo);
var imageHeightNode = propertySetNodeModulo.GetScalarProperty(imageHeightParam);
var imageWidthNode = propertySetNodeModulo.GetScalarProperty(imageWidthParam);
string GenerateFormula(string common, string dimension)
=> string.Format(
"{0} == 0 " +
"? 0 " +
": {0} < 0 " +
"? -(Abs({0} - (Ceil({0} / {1}) * {1})) % {1}) " +
": -({1} - ({0} % {1}))",
common,
dimension);
string expressionXVal;
string expressionYVal;
if (scrollViewer == null)
{
var offsetXNode = ExpressionFunctions.Ceil(propertySetNodeModulo.GetScalarProperty(offsetXParam));
var offsetYNode = ExpressionFunctions.Ceil(propertySetNodeModulo.GetScalarProperty(offsetYParam));
// expressions are created to simulate a positive and negative modulo with the size of the image and the offset
expressionXVal = ExpressionFunctions.Conditional(
offsetXNode == 0,
0,
ExpressionFunctions.Conditional(
offsetXNode < 0,
-(ExpressionFunctions.Abs(offsetXNode - (ExpressionFunctions.Ceil(offsetXNode / imageWidthNode) * imageWidthNode)) % imageWidthNode),
-(imageWidthNode - (offsetXNode % imageWidthNode))));
expressionXVal = GenerateFormula("Ceil(" + qualifiedOffsetXParam + ")", qualifiedImageHeightParam);
expressionYVal = ExpressionFunctions.Conditional(
offsetYNode == 0,
0,
ExpressionFunctions.Conditional(
offsetYNode < 0,
-(ExpressionFunctions.Abs(offsetYNode - (ExpressionFunctions.Ceil(offsetYNode / imageHeightNode) * imageHeightNode)) % imageHeightNode),
-(imageHeightNode - (offsetYNode % imageHeightNode))));
expressionYVal = GenerateFormula("Ceil(" + qualifiedOffsetYParam + ")", qualifiedImageWidthParam);
}
else
{
// expressions are created to simulate a positive and negative modulo with the size of the image and the offset and the ScrollViewer offset (Translation)
var scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
var scrollPropSet = scrollProperties.GetSpecializedReference<ManipulationPropertySetReferenceNode>();
const string scrollParam = "s";
const string translationParam = scrollParam + "." + nameof(scrollViewer.Translation);
const string qualifiedSpeedParam = propSetParam + "." + speedParam;
var speed = propertySetNodeModulo.GetScalarProperty(speedParam);
var xCommon = ExpressionFunctions.Ceil((scrollPropSet.Translation.X * speed) + propertySetNodeModulo.GetScalarProperty(offsetXParam));
expressionXVal = ExpressionFunctions.Conditional(
xCommon == 0,
0,
ExpressionFunctions.Conditional(
xCommon < 0,
-(ExpressionFunctions.Abs(xCommon - (ExpressionFunctions.Ceil(xCommon / imageWidthNode) * imageWidthNode)) % imageWidthNode),
-(imageWidthNode - (xCommon % imageWidthNode))));
expressionX.SetReferenceParameter(scrollParam, scrollProperties);
expressionY.SetReferenceParameter(scrollParam, scrollProperties);
var yCommon = ExpressionFunctions.Ceil((scrollPropSet.Translation.Y * speed) + propertySetNodeModulo.GetScalarProperty(offsetYParam));
expressionYVal = ExpressionFunctions.Conditional(
yCommon == 0,
0,
ExpressionFunctions.Conditional(
yCommon < 0,
-(ExpressionFunctions.Abs(yCommon - (ExpressionFunctions.Ceil(yCommon / imageHeightNode) * imageHeightNode)) % imageHeightNode),
-(imageHeightNode - (yCommon % imageHeightNode))));
string GenerateParallaxFormula(string scrollTranslation, string speed, string offset, string dimension)
=> GenerateFormula(string.Format("Ceil(({0} * {1}) + {2})", scrollTranslation, speed, offset), dimension);
expressionXVal = GenerateParallaxFormula(translationParam + "." + nameof(scrollViewer.Translation.X), qualifiedSpeedParam, qualifiedOffsetXParam, qualifiedImageWidthParam);
expressionYVal = GenerateParallaxFormula(translationParam + "." + nameof(scrollViewer.Translation.Y), qualifiedSpeedParam, qualifiedOffsetYParam, qualifiedImageHeightParam);
}
if (scrollOrientation == ScrollOrientation.Horizontal || scrollOrientation == ScrollOrientation.Both)
{
expressionX = expressionXVal;
expressionX.Expression = expressionXVal;
if (scrollOrientation == ScrollOrientation.Horizontal)
{
// In horizontal mode we never move the offset y
expressionY = (ScalarNode)0.0f;
expressionY.Expression = "0";
_containerVisual.Offset = new Vector3((float)OffsetY, 0, 0);
}
}
if (scrollOrientation == ScrollOrientation.Vertical || scrollOrientation == ScrollOrientation.Both)
{
expressionY = expressionYVal;
expressionY.Expression = expressionYVal;
if (scrollOrientation == ScrollOrientation.Vertical)
{
// In vertical mode we never move the offset x
expressionX = (ScalarNode)0.0f;
expressionX.Expression = "0";
_containerVisual.Offset = new Vector3(0, (float)OffsetX, 0);
}
}

Просмотреть файл

@ -6,7 +6,10 @@ using Microsoft.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
internal class PretokenStringContainer : DependencyObject, ITokenStringContainer
/// <summary>
/// <see cref="TokenizingTextBox"/> support class
/// </summary>
internal partial class PretokenStringContainer : DependencyObject, ITokenStringContainer
{
public string Text
{

Просмотреть файл

@ -168,7 +168,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
/// <summary>
/// A target for the <see cref="FocusBehavior"/>.
/// </summary>
public sealed class FocusTarget : DependencyObject
public sealed partial class FocusTarget : DependencyObject
{
/// <summary>
/// The DP to store the <see cref="Control"/> property value.

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Converters
/// This class converts a boolean value into an other object.
/// Can be used to convert true/false to visibility, a couple of colors, couple of images, etc.
/// </summary>
public class BoolToObjectConverter : DependencyObject, IValueConverter
public partial class BoolToObjectConverter : DependencyObject, IValueConverter
{
/// <summary>
/// Identifies the <see cref="TrueValue"/> property.

Просмотреть файл

@ -15,7 +15,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Converters
/// Otherwise the logic looks for the value to be GreaterThan or LessThan the specified value.
/// The ConverterParameter can be used to invert the logic.
/// </summary>
public class DoubleToObjectConverter : DependencyObject, IValueConverter
public partial class DoubleToObjectConverter : DependencyObject, IValueConverter
{
/// <summary>
/// Identifies the <see cref="TrueValue"/> property.

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Converters
/// This class converts an object value into a an object (if the value is null returns the false value).
/// Can be used to bind a visibility, a color or an image to the value of an object.
/// </summary>
public class EmptyObjectToObjectConverter : DependencyObject, IValueConverter
public partial class EmptyObjectToObjectConverter : DependencyObject, IValueConverter
{
/// <summary>
/// Identifies the <see cref="NotEmptyValue"/> property.

Просмотреть файл

@ -11,7 +11,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Converters
/// <summary>
/// This class returns an object or another, depending on whether the type of the provided value matches another provided Type.
/// </summary>
public class TypeToObjectConverter : DependencyObject, IValueConverter
public partial class TypeToObjectConverter : DependencyObject, IValueConverter
{
/// <summary>
/// Identifies the <see cref="TrueValue"/> property.

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Helpers
/// Can be used to change several objects' properties at a time.
/// </summary>
[ContentProperty(Name = nameof(Value))]
public class BindableValueHolder : DependencyObject
public partial class BindableValueHolder : DependencyObject
{
/// <summary>
/// Identifies the <see cref="Value"/> property.

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Title>Windows Community Toolkit UI</Title>
<Description>

Просмотреть файл

@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Windows.Storage;
@ -20,7 +21,9 @@ namespace Microsoft.Toolkit.Uwp.Helpers
/// <summary>
/// Initializes a new instance of the <see cref="BaseObjectStorageHelper"/> class,
/// which can read and write data using the provided <see cref="IObjectSerializer"/>;
/// if none is provided, a default Json serializer will be used.
/// if none is provided, a default Json serializer will be used (based on <see cref="DataContractSerializer"/>).
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json and the new default Serializer may behave differently.
/// To implement a <see cref="IObjectSerializer"/> based on Newtonsoft.Json or System.Text.Json see https://aka.ms/wct/storagehelper-migration
/// </summary>
/// <param name="objectSerializer">The serializer to use.</param>
public BaseObjectStorageHelper(IObjectSerializer objectSerializer = null)

Просмотреть файл

@ -2,14 +2,28 @@
// 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.Text.Json;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace Microsoft.Toolkit.Uwp.Helpers
{
internal class JsonObjectSerializer : IObjectSerializer
{
public string Serialize<T>(T value) => JsonSerializer.Serialize(value);
public string Serialize<T>(T value)
{
using var sr = new MemoryStream();
public T Deserialize<T>(string value) => JsonSerializer.Deserialize<T>(value);
new DataContractJsonSerializer(typeof(T)).WriteObject(sr, value);
var json = sr.ToArray();
return Encoding.UTF8.GetString(json, 0, json.Length);
}
public T Deserialize<T>(string value)
{
using var ms = new MemoryStream(Encoding.UTF8.GetBytes(value));
return (T)new DataContractJsonSerializer(typeof(T)).ReadObject(ms);
}
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// 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.Runtime.Serialization;
using Windows.Storage;
namespace Microsoft.Toolkit.Uwp.Helpers
@ -14,7 +15,9 @@ namespace Microsoft.Toolkit.Uwp.Helpers
/// <summary>
/// Initializes a new instance of the <see cref="LocalObjectStorageHelper"/> class,
/// which can read and write data using the provided <see cref="IObjectSerializer"/>;
/// if none is provided, a default Json serializer will be used.
/// if none is provided, a default Json serializer will be used (based on <see cref="DataContractSerializer"/>).
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json and the new default Serializer may behave differently.
/// To implement a <see cref="IObjectSerializer"/> based on Newtonsoft.Json or System.Text.Json see https://aka.ms/wct/storagehelper-migration
/// </summary>
/// <param name="objectSerializer">The serializer to use.</param>
public LocalObjectStorageHelper(IObjectSerializer objectSerializer = null)

Просмотреть файл

@ -2,6 +2,7 @@
// 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.Runtime.Serialization;
using Windows.Storage;
namespace Microsoft.Toolkit.Uwp.Helpers
@ -14,7 +15,9 @@ namespace Microsoft.Toolkit.Uwp.Helpers
/// <summary>
/// Initializes a new instance of the <see cref="RoamingObjectStorageHelper"/> class,
/// which can read and write data using the provided <see cref="IObjectSerializer"/>;
/// if none is provided, a default Json serializer will be used.
/// if none is provided, a default Json serializer will be used (based on <see cref="DataContractSerializer"/>).
/// In 6.1 and older the default Serializer was based on Newtonsoft.Json and the new default Serializer may behave differently.
/// To implement a <see cref="IObjectSerializer"/> based on Newtonsoft.Json or System.Text.Json see https://aka.ms/wct/storagehelper-migration
/// </summary>
/// <param name="objectSerializer">The serializer to use.</param>
public RoamingObjectStorageHelper(IObjectSerializer objectSerializer = null)

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<TargetFrameworks>net5.0-windows10.0.18362.0</TargetFrameworks>
<Title>Windows Community Toolkit</Title>
<Description>This package includes code only helpers such as Colors conversion tool, Storage file handling, a Stream helper class, etc.</Description>
<PackageTags>UWP Toolkit Windows</PackageTags>

Просмотреть файл

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="Microsoft.Toolkit.Uwp">
<Namespace Name="System.Text.Json.Serialization.Converters" Dynamic="Required All"/>
</Library>
</Directives>

Просмотреть файл

@ -6,6 +6,9 @@
<!-- When writting the SmokeTests, change this to whichever Toolkit project you want to build a test to, then reload the project -->
<CurrentProject>Microsoft.Toolkit.Uwp.UI.Controls</CurrentProject>
</PropertyGroup>
<PropertyGroup Condition="'$(NuGetPackageVersion)' == ''">
<NuGetPackageVersion>To Fill In With Local Version Number</NuGetPackageVersion>
</PropertyGroup>
<!-- - - - - - Don't check-in changes in between this lines. Used for development. - - - - - -->
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -112,18 +115,19 @@
<Version>2.4.3</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(CurrentProject)' != ''">
<PackageReference Include="$(CurrentProject)" Version="7.*-*" />
<ItemGroup Condition="'$(CurrentProject)' != '' and '$(CurrentProject)' != 'UWPBaseline' and '$(NuGetPackageVersion)' != 'To Fill In With Local Version Number'">
<PackageReference Include="$(CurrentProject)" Version="$(NuGetPackageVersion)" />
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<Target Name="BeforeBuild">
<ItemGroup>
<ItemGroup Condition="$(CurrentProject) != 'UWPBaseline'">
<ToolkitNugets Include="../bin/nupkg/$(CurrentProject).*.nupkg"/>
<ToolkitNuget Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Identity)', `$(CurrentProject).([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?.nupkg`))" Include="@(ToolkitNugets)"/>
</ItemGroup>
<Error Condition="'@(ToolkitNuget)' == ''" Text="NuGet $(CurrentProject).[SEMVER].nupkg doesn't exist!"/>
<Error Condition="'@(ToolkitNuget)' == '' and $(CurrentProject) != 'UWPBaseline'" Text="NuGet $(CurrentProject).[SEMVER].nupkg doesn't exist!"/>
<Error Condition="'$(CurrentProject)' != 'UWPBaseline' and '$(NuGetPackageVersion)' == 'To Fill In With Local Version Number'" Text="Please set NuGetPackageVersion at the top of SmokeTest.csproj with the version to smoke test locally."/>
</Target>
</Project>

Просмотреть файл

@ -5,6 +5,13 @@ VisualStudioVersion = 16.0.30413.136
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmokeTest", "SmokeTest.csproj", "{A6E4CB52-1025-4BBA-9C65-BB871D1FB53F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Configuration", "Configuration", "{86F3F991-6DDA-442D-A610-9309D6559522}"
ProjectSection(SolutionItems) = preProject
nuget.config = nuget.config
SmokeTestAnalysis.ps1 = SmokeTestAnalysis.ps1
SmokeTests.proj = SmokeTests.proj
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM

Просмотреть файл

@ -0,0 +1,149 @@
$ErrorActionPreference = "Stop"
$ProgressPreference="SilentlyContinue"
Write-Host "Running Smoke Test Package Analyis"
Write-Host "----------------------------------"
# Our script is at our SmokeTest root, we want to look for the AppPackages folder
$PackagePath = $PSScriptRoot + "\AppPackages\"
$FilePattern = "SmokeTest_{0}_x86_bundle.msixupload"
$BaselineName = $FilePattern -f "UWPBaseline"
$TempFolder = "ExplodedArchive"
function Expand-MsixUploadPackage {
param (
[string]$PackageFile,
[string]$Destination
)
$ZipUpload = $PackageFile.Replace("msixupload", "zip")
Move-Item $PackageFile -Destination $ZipUpload
Expand-Archive $ZipUpload -DestinationPath $Destination
Move-Item $ZipUpload -Destination $PackageFile
Push-Location $Destination
$Bundle = (Get-ChildItem "*.msixbundle").Name
$ZipBundle = $Bundle.Replace("msixbundle", "zip")
Move-Item $Bundle -Destination $ZipBundle
Expand-Archive $ZipBundle -DestinationPath .
Remove-Item $ZipBundle
$msix = (Get-ChildItem "*.msix").Name
$ZipMSIX = $msix.Replace("msix", "zip")
Move-Item $msix -Destination $ZipMSIX
Expand-Archive $ZipMSIX -DestinationPath . -Force # Force here as we have some duplicate file names we don't really care about from parent archives
Remove-Item $ZipMSIX
Pop-Location
}
if (Test-Path $PackagePath)
{
Push-Location $PackagePath
Write-Host "Extracting Baseline..."
# TODO: Theoretically we could grab bits from the bin directory instead of having to expand each package, not sure about what we ignore though
Expand-MsixUploadPackage $BaselineName -Destination $TempFolder
# Get all the base file info only (grab stuff in directories but not the directories themselves)
$BaselineFiles = Get-ChildItem $TempFolder -Recurse -Attributes !Directory -Exclude "SmokeTest*"
$SmokeTestFiles = Get-ChildItem $TempFolder -Recurse -Attributes !Directory -Include "SmokeTest*"
$BaselineFootprint = ($BaselineFiles | Measure-Object -Property Length -sum).Sum + ($SmokeTestFiles | Measure-Object -Property Length -sum).Sum
Write-Host ("Baseline Footprint: {0:n0} bytes" -f $BaselineFootprint)
Write-Host "-----------------------------------------"
$PackageList = Get-ChildItem "$PackagePath*.msixupload" -Exclude $BaselineName
#$i = 0
foreach ($Package in $PackageList)
{
#Write-Progress -Id 0 -Activity "Comparing Against Baseline..." -Status "Prepping Package" -PercentComplete (($i++ / $PackageList.count)*100) -CurrentOperation $Package.Name
# Make sure we've cleaned-up the last archive
Remove-Item $TempFolder -Recurse -Force
#$ProgressPreference="SilentlyContinue"
Expand-MsixUploadPackage $Package.Name -Destination $TempFolder
#$ProgressPreference="Continue"
[System.Collections.ArrayList]$PackageFiles = Get-ChildItem $TempFolder -Recurse -Attributes !Directory -Exclude "SmokeTest*"
$PackageSmokeTestFiles = Get-ChildItem $TempFolder -Recurse -Attributes !Directory -Include "SmokeTest*"
# TODO: Make function or regex better to extra package name more easily based on a template string at the top or something...
$PackageShortName = $Package.Name.substring(10, $Package.Name.Length - 32)
Write-Host ("{0} Additional Footprint: {1:n0} bytes" -f $PackageShortName, (($PackageFiles | Measure-Object -Property Length -sum).Sum + ($PackageSmokeTestFiles | Measure-Object -Property Length -sum).Sum - $BaselineFootprint))
# Quick check on the base exe file/symbols differences
foreach ($file in $SmokeTestFiles)
{
$match = $null
$match = $PackageSmokeTestFiles | Where-Object {$_.Extension -eq $file.Extension}
if ($null -ne $match)
{
Write-Host (" App Diff: ({0}) = {1:n0}" -f $file.Extension, ($match.Length - $file.Length)) -ForegroundColor DarkCyan
}
}
#$j = 0
foreach ($file in $BaselineFiles)
{
#Write-Progress -Id 1 -ParentId 0 -Activity "Comparing Against Baseline..." -Status "Comparing Package" -PercentComplete (($j++ / $BaselineFiles.count)*100) -CurrentOperation $file.Name
$match = $null
$match = $PackageFiles | Where-Object {$_.Name -eq $file.Name}
if ($null -ne $match)
{
# File was in baseline, but has a different size
if ($match.Length -ne $file.Length)
{
Write-Host (" Size Diff: {0} = {1:n0}" -f $file.Name, ($match.Length - $file.Length)) -ForegroundColor Magenta
}
# Remove checked files (performance) and also remaining are new
$PackageFiles.Remove($match)
}
}
# List remaining (new) files to this package
foreach ($file in $PackageFiles)
{
if ($file.Name -match $PackageShortName)
{
Write-Host (" Lib (self): {0} = {1:n0}" -f $file.Name, $file.Length) -ForegroundColor White
}
else
{
Write-Host (" Additional: {0} = {1:n0}" -f $file.Name, $file.Length) -ForegroundColor Yellow
}
}
# TODO: Especially if we add comparison to the main branch, we should format as an actual table and colorize via VT: https://stackoverflow.com/a/49038815/8798708
#Write-Progress -Id 1 -ParentId 0 -Activity "Comparing Against Baseline..." -Completed
Write-Host "-----------------------------------------"
Write-Host
}
#Write-Progress -Id 0 -Activity "Comparing Against Baseline..." -Completed
# Clean-up
Remove-Item $TempFolder -Recurse -Force
Pop-Location
}
else
{
Write-Error "Path $PackagePath not found for analysis!"
}

Просмотреть файл

@ -4,19 +4,29 @@
<PropertyGroup>
<BuildPlatforms>x86</BuildPlatforms>
<BuildConfigurations>Release</BuildConfigurations>
<ToolkitPackages>Microsoft.Toolkit;Microsoft.Toolkit.HighPerformance;Microsoft.Toolkit.Parsers;Microsoft.Toolkit.Mvvm;Microsoft.Toolkit.Services;Microsoft.Toolkit.Uwp;Microsoft.Toolkit.Uwp.Connectivity;Microsoft.Toolkit.Uwp.DeveloperTools;Microsoft.Toolkit.Uwp.Input.GazeInteraction;Microsoft.Toolkit.Uwp.Notifications;Microsoft.Toolkit.Uwp.UI;Microsoft.Toolkit.Uwp.UI.Animations;Microsoft.Toolkit.Uwp.UI.Controls;Microsoft.Toolkit.Uwp.UI.Controls.DataGrid;Microsoft.Toolkit.Uwp.UI.Controls.Layout;Microsoft.Toolkit.Uwp.UI.Media;Microsoft.Toolkit.Uwp.UI.Controls.Markdown</ToolkitPackages>
<ToolkitPackages>UWPBaseline;Microsoft.Toolkit;Microsoft.Toolkit.HighPerformance;Microsoft.Toolkit.Parsers;Microsoft.Toolkit.Mvvm;Microsoft.Toolkit.Services;Microsoft.Toolkit.Uwp;Microsoft.Toolkit.Uwp.Connectivity;Microsoft.Toolkit.Uwp.DeveloperTools;Microsoft.Toolkit.Uwp.Input.GazeInteraction;Microsoft.Toolkit.Uwp.Notifications;Microsoft.Toolkit.Uwp.UI;Microsoft.Toolkit.Uwp.UI.Animations;Microsoft.Toolkit.Uwp.UI.Controls;Microsoft.Toolkit.Uwp.UI.Controls.DataGrid;Microsoft.Toolkit.Uwp.UI.Controls.Layout;Microsoft.Toolkit.Uwp.UI.Media;Microsoft.Toolkit.Uwp.UI.Controls.Markdown</ToolkitPackages>
</PropertyGroup>
<Target Name="GetNuGetVersion">
<Exec Command="powershell -Command &quot;&amp; { .\&quot;$(ProjectDir)..\build\tools\Nerdbank.GitVersioning\tools\Get-Version.ps1\&quot; | Select -ExpandProperty NuGetPackageVersion }&quot;"
ConsoleToMSBuild="true"
EchoOff="true"
Condition="'$(NuGetPackageVersion)' == ''">
<Output TaskParameter="ConsoleOutput" PropertyName="NuGetPackageVersion" />
</Exec>
<Message Text="Got GitBank Version... $(NuGetPackageVersion)" Importance="High" />
</Target>
<Target Name="Build"
DependsOnTargets="ChooseProjectsToBuild"
DependsOnTargets="ChooseProjectsToBuild;GetNuGetVersion"
Inputs="@(ProjectsToBuild)"
Outputs="%(Filename)">
<Message Importance="High" Text="Building project %(ProjectsToBuild.Filename): (%(ProjectsToBuild.Configuration)|%(ProjectsToBuild.Platform))" />
<Message Importance="High" Text="Building project %(ProjectsToBuild.Identity): (%(ProjectsToBuild.Configuration)|%(ProjectsToBuild.Platform))" />
<MSBuild Projects="SmokeTest.csproj"
Targets="restore;build"
Properties="CurrentProject=%(ProjectsToBuild.Identity);Configuration=%(ProjectsToBuild.Configuration);Platform=%(ProjectsToBuild.Platform)"/>
Properties="CurrentProject=%(ProjectsToBuild.Identity);Configuration=%(ProjectsToBuild.Configuration);Platform=%(ProjectsToBuild.Platform);NuGetPackageVersion=$(NuGetPackageVersion)"/>
</Target>
<Target Name="ChooseProjectsToBuild" DependsOnTargets="CheckNugets">

Просмотреть файл

@ -1,15 +1,12 @@
<Page
x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.RegexStateTriggerPage"
x:Class="SmokeTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
xmlns:local="using:SmokeTest"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<!-- Dummy Resource for Optimization Protection -->
<triggers:RegexStateTrigger x:Key="RegexStateTrigger"/>
</Page.Resources>
<Grid/>
</Page>

Просмотреть файл

@ -0,0 +1,14 @@
// 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.
namespace SmokeTest
{
public sealed partial class MainPage
{
public MainPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -34,6 +34,7 @@ namespace UnitTests.Helpers
Assert.AreEqual(input, output);
}
[Ignore]
[TestCategory("Helpers")]
[TestMethod]
public void Test_StorageHelper_LegacyDateTest()
@ -53,19 +54,41 @@ namespace UnitTests.Helpers
Assert.AreEqual(input, output);
}
[Ignore]
[TestCategory("Helpers")]
[TestMethod]
public void Test_StorageHelper_LegacyPersonTest()
public void Test_StorageHelper_LegacyInternalClassTest()
{
string key = "Contact";
Person input = new Person() { Name = "Joe Bloggs", Age = 42 };
UI.Person input = new UI.Person() { Name = "Joe Bloggs", Age = 42 };
// simulate previous version by generating json and manually inserting it as string
string jsonInput = JsonSerializer.Serialize(input);
storageHelper.Save<string>(key, jsonInput);
// now read it as int to valid that the change works
UI.Person output = storageHelper.Read<UI.Person>(key, null);
Assert.IsNotNull(output);
Assert.AreEqual(input.Name, output.Name);
Assert.AreEqual(input.Age, output.Age);
}
[TestCategory("Helpers")]
[TestMethod]
public void Test_StorageHelper_LegacyPublicClassTest()
{
string key = "Contact";
UI.Person input = new UI.Person() { Name = "Joe Bloggs", Age = 42 };
// simulate previous version by generating json and manually inserting it as string
string jsonInput = JsonSerializer.Serialize(input);
storageHelper.Save(key, jsonInput);
// now read it as int to valid that the change works
Person output = storageHelper.Read<Person>(key, null);
@ -123,5 +146,12 @@ namespace UnitTests.Helpers
Assert.AreEqual(input.Name, output.Name);
Assert.AreEqual(input.Age, output.Age);
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
// 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.Automation;
using Microsoft.Toolkit.Uwp.UI.Controls;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
using Windows.UI.Xaml.Automation.Peers;
using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
namespace UnitTests.UWP.UI.Controls
{
[TestClass]
[TestCategory("Test_BladeView")]
public class Test_BladeView
{
[UITestMethod]
public void ShouldConfigureBladeViewAutomationPeer()
{
const string automationName = "MyAutomationBlades";
const string name = "MyBlades";
var bladeView = new BladeView();
var bladeViewAutomationPeer = FrameworkElementAutomationPeer.CreatePeerForElement(bladeView) as BladeViewAutomationPeer;
Assert.IsNotNull(bladeViewAutomationPeer, "Verify that the AutomationPeer is BladeViewAutomationPeer.");
bladeView.Name = name;
Assert.IsTrue(bladeViewAutomationPeer.GetName().Contains(name), "Verify that the UIA name contains the given Name of the BladeView.");
bladeView.SetValue(AutomationProperties.NameProperty, automationName);
Assert.IsTrue(bladeViewAutomationPeer.GetName().Contains(automationName), "Verify that the UIA name contains the given AutomationProperties.Name of the BladeView.");
}
}
}

Просмотреть файл

@ -41,9 +41,6 @@
<PackageReference Include="System.Xml.XPath.XmlDocument">
<Version>4.3.0</Version>
</PackageReference>
<PackageReference Include="System.Text.Json">
<Version>4.7.2</Version>
</PackageReference>
<ProjectReference Include="..\..\Microsoft.Toolkit.Mvvm\Microsoft.Toolkit.Mvvm.csproj" />
<ProjectReference Include="..\..\Microsoft.Toolkit.Parsers\Microsoft.Toolkit.Parsers.csproj" />
<ProjectReference Include="..\..\Microsoft.Toolkit.Services\Microsoft.Toolkit.Services.csproj" />

Просмотреть файл

@ -1,9 +1,11 @@
trigger:
- master
- dev/*
- rel/*
pr:
- master
- dev/*
- rel/*
pool:
@ -13,8 +15,9 @@ variables:
BuildConfiguration: Release
jobs:
- job: ToolkitBuild
timeoutInMinutes: 120
### BUILD ###
- job: BuildBits
timeoutInMinutes: 60
steps:
- task: BatchScript@1
@ -74,15 +77,10 @@ jobs:
- powershell: .\build\build.ps1 -target=Build
displayName: Build
### Unit Tests ###
# - powershell: .\build\build.ps1 -target=Test
# displayName: Test
# timeoutInMinutes: 15
- powershell: .\build\build.ps1 -target=Package
displayName: Package
# - powershell: .\build\build.ps1 -target=SmokeTest
# displayName: SmokeTest
- task: PublishTestResults@2
inputs:
@ -91,20 +89,30 @@ jobs:
displayName: Publish Test Results
condition: always()
# - task: PublishPipelineArtifact@1
# displayName: Publish UI Test Results
# inputs:
# targetPath: .\build\UITestResults.wtl
# artifactName: WexLogFileOutput
# condition: always()
# - task: PublishPipelineArtifact@1
# displayName: Publish Test WexLogFileOutput
# inputs:
# targetPath: .\build\WexLogFileOutput
# artifactName: WexErrorLogFileOutput
# artifactName: WexUnitTestErrorLogFileOutput
# condition: failed()
### UI Integration Tests ###
# - powershell: .\build\build.ps1 -target=UITest
# displayName: UI Integration Tests
# - task: PublishPipelineArtifact@1
# displayName: Publish UI Test Results
# inputs:
# targetPath: .\build\UITestResults.wtl
# artifactName: WexUITestLogFileOutput
# condition: always()
### Package ###
- powershell: .\build\build.ps1 -target=Package
displayName: Package
- task: PowerShell@2
displayName: Authenticode Sign Packages
inputs:
@ -115,13 +123,28 @@ jobs:
ArtifactDirectory: bin\nupkg
condition: and(succeeded(), not(eq(variables['build.reason'], 'PullRequest')), not(eq(variables['SignClientSecret'], '')), not(eq(variables['SignClientUser'], '')))
- task: PublishBuildArtifacts@1
- task: PublishPipelineArtifact@1
displayName: Publish Package Artifacts
inputs:
pathToPublish: .\bin\nupkg
artifactType: container
targetPath: .\bin\nupkg
artifactName: Packages
### Smoke Tests ###
#- job: SmokeTests
# dependsOn: BuildBits
# timeoutInMinutes: 60
#
# steps:
# - task: DownloadPipelineArtifact@2
# displayName: Download NuGet Packages Artifact
# inputs:
# artifact: Packages
# path: .\bin\nupkg
#
# - powershell: .\build\build.ps1 -target=SmokeTest
# displayName: SmokeTest
#
# - task: CopyFiles@2
# inputs:
# sourceFolder: .\SmokeTests\AppPackages
@ -134,3 +157,6 @@ jobs:
# pathToPublish: $(build.artifactstagingdirectory)\SmokeTestBundles
# artifactType: container
# artifactName: SmokeTestBundles
#
# - powershell: .\SmokeTests\SmokeTestAnalysis.ps1
# displayName: Analyze Package Sizes

Просмотреть файл

@ -148,7 +148,6 @@ Task("Verify")
Task("Version")
.Description("Updates the version information in all Projects")
.IsDependentOn("Verify")
.Does(() =>
{
Information("\nDownloading NerdBank GitVersioning...");
@ -229,6 +228,7 @@ Task("InheritDoc")
Task("Build")
.Description("Build all projects runs InheritDoc")
.IsDependentOn("Verify")
.IsDependentOn("BuildProjects")
.IsDependentOn("InheritDoc");
@ -263,7 +263,7 @@ public string getMSTestAdapterPath(){
}
Task("Test")
.Description("Runs all Tests")
.Description("Runs all Unit Tests")
.Does(() =>
{
Information("\nRunning Unit Tests");
@ -292,7 +292,11 @@ Task("Test")
ArgumentCustomization = arg => arg.Append($"-s {baseDir}/.runsettings"),
};
DotNetCoreTest(file.FullPath, testSettings);
}).DoesForEach(GetFiles(taefBinDir + "/**/UITests.Tests.TAEF.dll"), (file) =>
}).DeferOnError();
Task("UITest")
.Description("Runs all UI Tests")
.DoesForEach(GetFiles(taefBinDir + "/**/UITests.Tests.TAEF.dll"), (file) =>
{
Information("\nRunning TAEF Interaction Tests");
@ -305,10 +309,19 @@ Task("Test")
Task("SmokeTest")
.Description("Runs all Smoke Tests")
.IsDependentOn("Version")
.Does(() =>
{
// Need to do full NuGet restore here to grab proper UWP dependencies...
NuGetRestore(baseDir + "/SmokeTests/SmokeTest.csproj");
MSBuild(baseDir + "/SmokeTests/SmokeTests.proj");
var buildSettings = new MSBuildSettings()
{
Restore = true,
}
.WithProperty("NuGetPackageVersion", Version);
MSBuild(baseDir + "/SmokeTests/SmokeTests.proj", buildSettings);
}).DeferOnError();
Task("MSTestUITest")
@ -335,6 +348,7 @@ Task("MSTestUITest")
Task("Default")
.IsDependentOn("Build")
//.IsDependentOn("Test")
//.IsDependentOn("UITest")
.IsDependentOn("Package");
Task("UpdateHeaders")