Skip to content

Commit

Permalink
Merge pull request #3518 from windows-toolkit/jamesmcroft/3517-bladev…
Browse files Browse the repository at this point in the history
…iew-automation

Added automation peers for BladeView and BladeItem controls
  • Loading branch information
michael-hawker authored Dec 15, 2020
2 parents c402640 + 32e3c4b commit 8ccfaff
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public partial class BladeItem
/// </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>
Expand Down Expand Up @@ -84,6 +86,16 @@ public bool IsOpen
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;
Expand Down
11 changes: 11 additions & 0 deletions Microsoft.Toolkit.Uwp.UI.Controls/BladeView/BladeItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

using System;
using Microsoft.Toolkit.Uwp.Extensions;
using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Controls;

namespace Microsoft.Toolkit.Uwp.UI.Controls
Expand Down Expand Up @@ -92,6 +94,15 @@ protected override void OnCollapsed(EventArgs args)
}
}

/// <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)
Expand Down
163 changes: 163 additions & 0 deletions Microsoft.Toolkit.Uwp.UI.Controls/BladeView/BladeItemAutomationPeer.cs
Original file line number Diff line number Diff line change
@@ -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 Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.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;
}
}
}
12 changes: 12 additions & 0 deletions Microsoft.Toolkit.Uwp.UI.Controls/BladeView/BladeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
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 Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Controls;

namespace Microsoft.Toolkit.Uwp.UI.Controls
Expand Down Expand Up @@ -65,6 +67,7 @@ protected override void PrepareContainerForItemOverride(DependencyObject element
if (blade != null)
{
blade.VisibilityChanged += BladeOnVisibilityChanged;
blade.ParentBladeView = this;
}

base.PrepareContainerForItemOverride(element, item);
Expand All @@ -83,6 +86,15 @@ protected override void ClearContainerForItemOverride(DependencyObject element,
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>();
Expand Down
115 changes: 115 additions & 0 deletions Microsoft.Toolkit.Uwp.UI.Controls/BladeView/BladeViewAutomationPeer.cs
Original file line number Diff line number Diff line change
@@ -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 Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Automation.Peers;
using Windows.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;
}
}
}
Loading

0 comments on commit 8ccfaff

Please sign in to comment.