Merge branch 'master' into shweaver/inappnotifications

This commit is contained in:
Kyaa Dost 2021-03-02 14:16:56 -08:00 коммит произвёл GitHub
Родитель 5932530c5e 5f87b232ac
Коммит 73be0aa7eb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
15 изменённых файлов: 504 добавлений и 29 удалений

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

@ -11,5 +11,10 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.Data
public string Category { get; set; }
public string Thumbnail { get; set; }
public override string ToString()
{
return Title;
}
}
}

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

@ -19,7 +19,6 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<ProjectReference Include="..\Microsoft.Toolkit.Uwp.UI\Microsoft.Toolkit.Uwp.UI.csproj" />
</ItemGroup>

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

@ -93,28 +93,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Automation.Peers
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>

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

@ -5,9 +5,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
@ -520,6 +522,17 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
{
carouselItem.IsSelected = true;
}
carouselItem.ParentCarousel = this;
}
/// <summary>
/// Creates AutomationPeer (<see cref="UIElement.OnCreateAutomationPeer"/>)
/// </summary>
/// <returns>An automation peer for this <see cref="Carousel"/>.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
return new CarouselAutomationPeer(this);
}
private void OnCarouselItemSelected(object sender, EventArgs e)
@ -528,5 +541,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
SelectedItem = ItemFromContainer(item);
}
internal void SetSelectedItem(CarouselItem owner)
{
var item = ItemFromContainer(owner);
SelectedItem = item;
}
}
}

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

@ -0,0 +1,143 @@
// 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 Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Automation.Provider;
using Windows.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.UI.Automation.Peers
{
/// <summary>
/// Defines a framework element automation peer for the <see cref="Carousel"/> control.
/// </summary>
public class CarouselAutomationPeer : ItemsControlAutomationPeer, ISelectionProvider
{
/// <summary>
/// Initializes a new instance of the <see cref="CarouselAutomationPeer"/> class.
/// </summary>
/// <param name="owner">
/// The <see cref="Carousel" /> that is associated with this <see cref="T:Windows.UI.Xaml.Automation.Peers.CarouselAutomationPeer" />.
/// </param>
public CarouselAutomationPeer(Carousel owner)
: base(owner)
{
}
/// <summary>Gets a value indicating whether the Microsoft UI Automation provider allows more than one child element to be selected concurrently.</summary>
/// <returns>True if multiple selection is allowed; otherwise, false.</returns>
public bool CanSelectMultiple => false;
/// <summary>Gets a value indicating whether the UI Automation provider requires at least one child element to be selected.</summary>
/// <returns>True if selection is required; otherwise, false.</returns>
public bool IsSelectionRequired => true;
private Carousel OwningCarousel
{
get
{
return Owner as Carousel;
}
}
/// <summary>Retrieves a UI Automation provider for each child element that is selected.</summary>
/// <returns>An array of UI Automation providers.</returns>
public IRawElementProviderSimple[] GetSelection()
{
return OwningCarousel.ContainerFromItem(this.OwningCarousel.SelectedItem) is CarouselItem selectedCarouselItem
? new[] { this.ProviderFromPeer(FromElement(selectedCarouselItem)) }
: new IRawElementProviderSimple[] { };
}
/// <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 Carousel
/// - Carousel class name
/// </returns>
protected override string GetNameCore()
{
string name = this.OwningCarousel.Name;
if (!string.IsNullOrEmpty(name))
{
return name;
}
name = AutomationProperties.GetName(this.OwningCarousel);
if (!string.IsNullOrEmpty(name))
{
return name;
}
return base.GetNameCore();
}
/// <summary>
/// Gets the control pattern that is associated with the specified Windows.UI.Xaml.Automation.Peers.PatternInterface.
/// </summary>
/// <param name="patternInterface">A value from the Windows.UI.Xaml.Automation.Peers.PatternInterface enumeration.</param>
/// <returns>The object that supports the specified pattern, or null if unsupported.</returns>
protected override object GetPatternCore(PatternInterface patternInterface)
{
switch (patternInterface)
{
case PatternInterface.Selection:
return this;
}
return base.GetPatternCore(patternInterface);
}
/// <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()
{
Carousel owner = OwningCarousel;
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 CarouselItem element)
{
peers.Add(FromElement(element) ?? CreatePeerForElement(element));
}
}
return peers;
}
}
}

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

@ -3,8 +3,9 @@
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Input;
@ -22,6 +23,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
private const string SelectedState = "Selected";
private const string NormalState = "Normal";
private WeakReference<Carousel> parentCarousel;
/// <summary>
/// Initializes a new instance of the <see cref="CarouselItem"/> class.
/// </summary>
@ -33,6 +36,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
RegisterPropertyChangedCallback(SelectorItem.IsSelectedProperty, OnIsSelectedChanged);
}
internal Carousel ParentCarousel
{
get
{
this.parentCarousel.TryGetTarget(out var carousel);
return carousel;
}
set => this.parentCarousel = new WeakReference<Carousel>(value);
}
/// <inheritdoc/>
protected override void OnPointerEntered(PointerRoutedEventArgs e)
{
@ -57,6 +70,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
VisualStateManager.GoToState(this, IsSelected ? PressedSelectedState : PressedState, true);
}
/// <summary>
/// Creates AutomationPeer (<see cref="UIElement.OnCreateAutomationPeer"/>)
/// </summary>
/// <returns>An automation peer for this <see cref="CarouselItem"/>.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
return new CarouselItemAutomationPeer(this);
}
internal event EventHandler Selected;
private void OnIsSelectedChanged(DependencyObject sender, DependencyProperty dp)

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

@ -0,0 +1,188 @@
// 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 Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Automation.Provider;
using Windows.UI.Xaml.Controls;
namespace Microsoft.Toolkit.Uwp.UI.Automation.Peers
{
/// <summary>
/// Defines a framework element automation peer for the <see cref="CarouselItem"/>.
/// </summary>
public class CarouselItemAutomationPeer : FrameworkElementAutomationPeer, ISelectionItemProvider
{
/// <summary>
/// Initializes a new instance of the <see cref="CarouselItemAutomationPeer"/> class.
/// </summary>
/// <param name="owner">
/// The <see cref="CarouselItem" /> that is associated with this <see cref="T:Windows.UI.Xaml.Automation.Peers.CarouselItemAutomationPeer" />.
/// </param>
public CarouselItemAutomationPeer(CarouselItem owner)
: base(owner)
{
}
/// <summary>Gets a value indicating whether an item is selected.</summary>
/// <returns>True if the element is selected; otherwise, false.</returns>
public bool IsSelected => this.OwnerCarouselItem.IsSelected;
/// <summary>Gets the UI Automation provider that implements ISelectionProvider and acts as the container for the calling object.</summary>
/// <returns>The UI Automation provider.</returns>
public IRawElementProviderSimple SelectionContainer
{
get
{
Carousel parent = this.OwnerCarouselItem.ParentCarousel;
if (parent == null)
{
return null;
}
AutomationPeer peer = FromElement(parent);
return peer != null ? this.ProviderFromPeer(peer) : null;
}
}
private CarouselItem OwnerCarouselItem
{
get { return this.Owner as CarouselItem; }
}
/// <summary>Adds the current element to the collection of selected items.</summary>
public void AddToSelection()
{
CarouselItem owner = this.OwnerCarouselItem;
Carousel parent = owner.ParentCarousel;
parent?.SetSelectedItem(owner);
}
/// <summary>Removes the current element from the collection of selected items.</summary>
public void RemoveFromSelection()
{
// Cannot remove the selection of a Carousel control.
}
/// <summary>Clears any existing selection and then selects the current element.</summary>
public void Select()
{
CarouselItem owner = this.OwnerCarouselItem;
Carousel parent = owner.ParentCarousel;
parent?.SetSelectedItem(owner);
}
/// <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 CarouselItem
/// - Carousel class name
/// </returns>
protected override string GetNameCore()
{
string name = AutomationProperties.GetName(this.OwnerCarouselItem);
if (!string.IsNullOrEmpty(name))
{
return name;
}
name = this.OwnerCarouselItem.Name;
if (!string.IsNullOrEmpty(name))
{
return name;
}
var textBlock = this.OwnerCarouselItem.FindDescendant<TextBlock>();
if (textBlock != null)
{
return textBlock.Text;
}
return base.GetNameCore();
}
/// <summary>
/// Gets the control pattern that is associated with the specified Windows.UI.Xaml.Automation.Peers.PatternInterface.
/// </summary>
/// <param name="patternInterface">A value from the Windows.UI.Xaml.Automation.Peers.PatternInterface enumeration.</param>
/// <returns>The object that supports the specified pattern, or null if unsupported.</returns>
protected override object GetPatternCore(PatternInterface patternInterface)
{
switch (patternInterface)
{
case PatternInterface.SelectionItem:
return this;
}
return base.GetPatternCore(patternInterface);
}
/// <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;
}
CarouselItem owner = this.OwnerCarouselItem;
Carousel parent = owner.ParentCarousel;
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;
}
CarouselItem owner = this.OwnerCarouselItem;
Carousel parent = owner.ParentCarousel;
positionInSet = parent.IndexFromContainer(owner) + 1;
return positionInSet;
}
}
}

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

@ -110,12 +110,12 @@
</PackageReference>
</ItemGroup>
<!-- Only the Layout package have a dependency on WinUI -->
<ItemGroup Condition="$(CurrentProject) == 'Microsoft.Toolkit.Uwp.UI.Controls.Layout'">
<ItemGroup Condition="$(CurrentProject) == 'UWPBaselineWinUI' or $(CurrentProject) == 'Microsoft.Toolkit.Uwp.UI.Controls.Layout'">
<PackageReference Include="Microsoft.UI.Xaml">
<Version>2.4.3</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(CurrentProject)' != '' and '$(CurrentProject)' != 'UWPBaseline' and '$(NuGetPackageVersion)' != 'To Fill In With Local Version Number'">
<ItemGroup Condition="'$(CurrentProject)' != '' and '$(CurrentProject)' != 'UWPBaseline' and '$(CurrentProject)' != 'UWPBaselineWinUI' and '$(NuGetPackageVersion)' != 'To Fill In With Local Version Number'">
<PackageReference Include="$(CurrentProject)" Version="$(NuGetPackageVersion)" />
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
@ -123,11 +123,11 @@
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<Target Name="BeforeBuild">
<ItemGroup Condition="$(CurrentProject) != 'UWPBaseline'">
<ItemGroup Condition="$(CurrentProject) != 'UWPBaseline' and '$(CurrentProject)' != 'UWPBaselineWinUI'">
<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)' == '' 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."/>
<Error Condition="'@(ToolkitNuget)' == '' and $(CurrentProject) != 'UWPBaseline' and '$(CurrentProject)' != 'UWPBaselineWinUI'" Text="NuGet $(CurrentProject).[SEMVER].nupkg doesn't exist!"/>
<Error Condition="'$(CurrentProject)' != 'UWPBaseline' and '$(CurrentProject)' != 'UWPBaselineWinUI' 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>

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

@ -6,6 +6,7 @@
<BuildConfigurations>Release</BuildConfigurations>
<ToolkitPackages>
UWPBaseline;
UWPBaselineWinUI;
Microsoft.Toolkit;
Microsoft.Toolkit.Diagnostics;
Microsoft.Toolkit.HighPerformance;

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

@ -0,0 +1,13 @@
<Page
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:SmokeTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<muxc:NavigationView/>
</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();
}
}
}

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

@ -37,5 +37,7 @@
<Type Name="Microsoft.Toolkit.Uwp.UI.SymbolIconSourceExtension" Dynamic="Required All" Serialize="Required All"/>
<Type Name="Microsoft.Toolkit.Uwp.UI.EnumValuesExtension" Dynamic="Required All" Serialize="Required All"/>
<Type Name="System.Collections.Generic.IList{Windows.UI.Xaml.Automation.Peers.AutomationPeer}" MarshalObject="Required All"/>
</Application>
</Directives>

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

@ -0,0 +1,86 @@
// 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.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml.Automation;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Windows.UI.Xaml.Automation.Peers;
using Microsoft.Toolkit.Uwp;
using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
using Microsoft.Toolkit.Uwp.UI.Controls;
namespace UnitTests.UWP.UI.Controls
{
[TestClass]
[TestCategory("Test_Carousel")]
public class Test_Carousel : VisualUITestBase
{
[TestMethod]
public async Task ShouldConfigureCarouselAutomationPeerAsync()
{
await App.DispatcherQueue.EnqueueAsync(async () =>
{
const int expectedSelectedIndex = 1;
const string expectedCarouselAutomationName = "MyAutomationPhotoItems";
const string expectedCarouselName = "MyPhotoItems";
var items = new ObservableCollection<PhotoDataItem> { new PhotoDataItem { Title = "Hello" }, new PhotoDataItem { Title = "World" } };
var carousel = new Carousel { ItemsSource = items };
await SetTestContentAsync(carousel);
// Sets the selected item to "World" from the items above.
carousel.SelectedIndex = expectedSelectedIndex;
var carouselAutomationPeer =
FrameworkElementAutomationPeer.CreatePeerForElement(carousel) as CarouselAutomationPeer;
Assert.IsNotNull(carouselAutomationPeer, "Verify that the AutomationPeer is CarouselAutomationPeer.");
Assert.IsFalse(carouselAutomationPeer.CanSelectMultiple, "Verify that CarouselAutomationPeer.CanSelectMultiple is false.");
Assert.IsTrue(carouselAutomationPeer.IsSelectionRequired, "Verify that CarouselAutomationPeer.IsSelectionRequired is true.");
// Asserts the automation peer name based on the Automation Property Name value.
carousel.SetValue(AutomationProperties.NameProperty, expectedCarouselAutomationName);
Assert.IsTrue(carouselAutomationPeer.GetName().Contains(expectedCarouselAutomationName), "Verify that the UIA name contains the given AutomationProperties.Name of the Carousel.");
// Asserts the automation peer name based on the element Name property.
carousel.Name = expectedCarouselName;
Assert.IsTrue(carouselAutomationPeer.GetName().Contains(expectedCarouselName), "Verify that the UIA name contains the given Name of the Carousel.");
var carouselItemAutomationPeers = carouselAutomationPeer.GetChildren().Cast<CarouselItemAutomationPeer>().ToList();
Assert.AreEqual(items.Count, carouselItemAutomationPeers.Count);
// Asserts the default calculated position in set and size of set values
for (var i = 0; i < carouselItemAutomationPeers.Count; i++)
{
var peer = carouselItemAutomationPeers[i];
Assert.AreEqual(i + 1, peer.GetPositionInSet());
Assert.AreEqual(items.Count, peer.GetSizeOfSet());
}
// Asserts the CarouselItemAutomationPeer properties
var selectedItemPeer = carouselItemAutomationPeers.FirstOrDefault(peer => peer.IsSelected);
Assert.IsNotNull(selectedItemPeer);
Assert.IsTrue(selectedItemPeer.GetName().Contains(items[expectedSelectedIndex].ToString()));
});
}
public class PhotoDataItem
{
public string Title { get; set; }
public string Category { get; set; }
public string Thumbnail { get; set; }
public override string ToString()
{
return Title;
}
}
}
}

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

@ -194,6 +194,7 @@
<Compile Include="PrivateType.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Helpers\Test_WeakEventListener.cs" />
<Compile Include="UI\Controls\Test_Carousel.cs" />
<Compile Include="UI\Controls\Test_BladeView.cs" />
<Compile Include="UI\Controls\Test_RadialGauge.cs" />
<Compile Include="UI\Controls\Test_TextToolbar_Localization.cs" />

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

@ -203,6 +203,10 @@
<Project>{805f80df-75c6-4c2f-8fd9-b47f6d0df5a3}</Project>
<Name>Microsoft.Toolkit.Uwp</Name>
</ProjectReference>
<ProjectReference Include="..\..\Microsoft.Toolkit\Microsoft.Toolkit.csproj">
<Project>{6fe128a8-cefa-4a61-a987-ec92de6b538e}</Project>
<Name>Microsoft.Toolkit</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Include="TestsPage.xaml">