Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VoiceCommand trigger added to Microsoft.Toolkit.Uwp.UI.Behaviors (#3392) #3661

Draft
wants to merge 9 commits into
base: dev/new-animations
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@
<Content Include="SamplePages\ViewExtensions\ViewExtensions.png" />
<Content Include="SamplePages\ViewportBehavior\ViewportBehavior.png" />
<Content Include="SamplePages\Visual Extensions\VisualExtensions.png" />
<Content Include="SamplePages\VoiceCommands\VoiceCommands.png" />
<Content Include="SamplePages\Weibo Service\WeiboLogo.png" />
<Content Include="SamplePages\WrapLayout\WrapLayout.png" />
<Content Include="SamplePages\WrapPanel\WrapPanel.png" />
Expand Down Expand Up @@ -546,6 +547,11 @@
<Compile Include="SamplePages\Triggers\IsNullOrEmptyStateTriggerPage.xaml.cs">
<DependentUpon>IsNullOrEmptyStateTriggerPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\VoiceCommands\ClickAction.cs" />
<Compile Include="SamplePages\VoiceCommands\VoiceCommandsPage.xaml.cs">
<DependentUpon>VoiceCommandsPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\VoiceCommands\SelectListBoxItemAction.cs" />
<Compile Include="SamplePages\WrapLayout\WrapLayoutPage.xaml.cs">
<DependentUpon>WrapLayoutPage.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -1350,6 +1356,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SamplePages\VoiceCommands\VoiceCommandsPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="SamplePages\WeatherLiveTileAndToast\WeatherLiveTileAndToastPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down
1 change: 1 addition & 0 deletions Microsoft.Toolkit.Uwp.SampleApp/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@
<DeviceCapability Name="bluetooth" />
<DeviceCapability Name="webcam" />
<DeviceCapability Name="gazeInput" />
<DeviceCapability Name="microphone"/>
</Capabilities>
</Package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 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.Xaml.Interactivity;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation.Peers;
using Windows.UI.Xaml.Automation.Provider;
using Windows.UI.Xaml.Controls;

namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
public class ClickAction : DependencyObject, IAction
{
public object Execute(object sender, object parameter)
{
if (sender is Button btn && btn.IsEnabled)
{
var peer = new ButtonAutomationPeer(btn);
var invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProv?.Invoke();
}

return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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.Xaml.Interactivity;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
public class SelectListBoxItemAction : DependencyObject, IAction
{
public Direction MoveDirection
{
get => (Direction)GetValue(MoveDirectionProperty);
set => SetValue(MoveDirectionProperty, value);
}

public static readonly DependencyProperty MoveDirectionProperty = DependencyProperty.Register(nameof(MoveDirection), typeof(Direction), typeof(SelectListBoxItemAction), new PropertyMetadata(default(Direction)));

public object Execute(object sender, object parameter)
{
if (sender is ListBox lb)
{
var selectedIndex = lb.SelectedIndex;
switch (MoveDirection)
{
case Direction.Up when selectedIndex > 0:
lb.SelectedIndex--;
break;
case Direction.Down when selectedIndex < lb.Items.Count - 1:
lb.SelectedIndex++;
break;
case Direction.First when lb.Items.Count > 0:
lb.SelectedIndex = 0;
break;
case Direction.Last when lb.Items.Count > 0:
lb.SelectedIndex = lb.Items.Count - 1;
break;
default:
break;
}
}

return null;
}

public enum Direction
{
Up,
Down,
First,
Last
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.VoiceCommandsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
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"
x:Name="pageRoot"
mc:Ignorable="d">

<Grid Padding="12"
ColumnSpacing="12"
RowSpacing="12">

<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>

<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<TextBlock Text="Available" />

<ListBox x:Name="listBoxAvailable"
Grid.Row="1"
Grid.RowSpan="3"
SelectedIndex="0">
<Interactivity:Interaction.Behaviors>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Move available up">
<local:SelectListBoxItemAction MoveDirection="Up" />
</Behaviors:VoiceCommandTrigger>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Move available down">
<local:SelectListBoxItemAction MoveDirection="Down" />
</Behaviors:VoiceCommandTrigger>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Move available to First|Move available too First">
<local:SelectListBoxItemAction MoveDirection="First" />
</Behaviors:VoiceCommandTrigger>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Move available to Last|Move available too Last">
<local:SelectListBoxItemAction MoveDirection="Last" />
</Behaviors:VoiceCommandTrigger>
</Interactivity:Interaction.Behaviors>

<ListBoxItem Content="Ford" />
<ListBoxItem Content="BMW" />
<ListBoxItem Content="VW" />
<ListBoxItem Content="Audi" />
<ListBoxItem Content="Porche" />
<ListBoxItem Content="Mercedes" />
<ListBoxItem Content="Honda" />
<ListBoxItem Content="Toyota" />
</ListBox>

<Button x:Uid="ButtonAdd"
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Stretch"
Click="ButtonAdd_Click"
Content="&gt; Add &gt;">
<Interactivity:Interaction.Behaviors>
<Behaviors:VoiceCommandTrigger x:Uid="CommandAdd"
IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Add|at">
<local:ClickAction />
</Behaviors:VoiceCommandTrigger>
</Interactivity:Interaction.Behaviors>
</Button>

<TextBlock Grid.Column="2"
Text="Selected" />

<ListBox x:Name="listBoxSelected"
Grid.Row="1"
Grid.RowSpan="2"
Grid.Column="2">
<Interactivity:Interaction.Behaviors>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Move selected up">
<local:SelectListBoxItemAction MoveDirection="Up" />
</Behaviors:VoiceCommandTrigger>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Move selected down">
<local:SelectListBoxItemAction MoveDirection="Down" />
</Behaviors:VoiceCommandTrigger>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Move selected to First|Move selected too First">
<local:SelectListBoxItemAction MoveDirection="First" />
</Behaviors:VoiceCommandTrigger>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Move selected to Last|Move selected too Last">
<local:SelectListBoxItemAction MoveDirection="Last" />
</Behaviors:VoiceCommandTrigger>
</Interactivity:Interaction.Behaviors>
</ListBox>

<Button x:Uid="ButtonDelete"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Click="ButtonDelete_Click"
Content="&lt; Delete &lt;">
<Interactivity:Interaction.Behaviors>
<Behaviors:VoiceCommandTrigger x:Uid="CommandDelete"
IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="Delete">
<local:ClickAction />
</Behaviors:VoiceCommandTrigger>
</Interactivity:Interaction.Behaviors>
</Button>

<Grid Grid.Row="3"
Grid.Column="2"
ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

<TextBox x:Name="textBoxExtraItem"
Header="Extra item" />
<Button Grid.Column="1"
VerticalAlignment="Bottom"
Click="ButtonAppend_Click"
Content="Append"
Style="{StaticResource AccentButtonStyle}">
<Interactivity:Interaction.Behaviors>
<Behaviors:VoiceCommandTrigger Text="Append">
<local:ClickAction />
</Behaviors:VoiceCommandTrigger>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>

<Button Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Click="{x:Bind WhatCanISay}"
Content="What can I say?">
<Interactivity:Interaction.Behaviors>
<Behaviors:VoiceCommandTrigger x:Uid="CommandAdd"
IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="What can I say|Help">
<local:ClickAction />
</Behaviors:VoiceCommandTrigger>
</Interactivity:Interaction.Behaviors>
</Button>

<ToggleSwitch x:Name="toggleListning"
Grid.Row="3"
Grid.Column="1"
VerticalAlignment="Bottom"
Header="Voice"
IsOn="True"
Toggled="ToggleListning_Toggled">
<Interactivity:Interaction.Behaviors>
<Behaviors:VoiceCommandTrigger x:Name="triggerListning"
Text="Voice Off">
<core:ChangePropertyAction x:Name="actionListning"
PropertyName="IsOn"
TargetObject="{x:Bind toggleListning}"
Value="false" />
</Behaviors:VoiceCommandTrigger>
</Interactivity:Interaction.Behaviors>
</ToggleSwitch>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Microsoft.Toolkit.Uwp.UI.Behaviors;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.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 VoiceCommandsPage : Page
{
public VoiceCommandsPage()
{
this.InitializeComponent();
this.Loaded += this.VoiceCommandsPage_Loaded;
}

private async void VoiceCommandsPage_Loaded(object sender, RoutedEventArgs e)
{
if (VoiceCommandTrigger.SpeechRecognizer is null)
{
VoiceCommandTrigger.SpeechRecognizer = await WindowsMediaSpeechRecognizer.CreateAsync(Window.Current);
}
}

private void ButtonAdd_Click(object sender, RoutedEventArgs e)
{
MoveItem(listBoxAvailable, listBoxSelected);
}

private void MoveItem(ListBox from, ListBox to)
{
var selectedIndex = from.SelectedIndex;
var selectedItem = from.SelectedItem;
if (selectedIndex > -1)
{
from.Items.RemoveAt(selectedIndex);
from.SelectedIndex = Math.Min(selectedIndex, from.Items.Count - 1);
to.Items.Add(selectedItem);
to.SelectedIndex = to.Items.Count - 1;
}
}

private void ButtonDelete_Click(object sender, RoutedEventArgs e)
{
MoveItem(listBoxSelected, listBoxAvailable);
}

private void ButtonAppend_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(textBoxExtraItem.Text))
{
listBoxSelected.Items.Add(new ListBoxItem
{
Content = textBoxExtraItem.Text
});
listBoxSelected.SelectedIndex = listBoxSelected.Items.Count - 1;
textBoxExtraItem.Text = string.Empty;
}
}

public void WhatCanISay()
{
string content = "You can speak the following voice commands: \r\n" +
"- What can I say\r\n" +
"- Help \r\n" +
"- Add\r\n" +
"- Delete\r\n" +
"- Move avaiable up\r\n" +
"- Move avaiable down\r\n" +
"- Move avaiable to First\r\n" +
"- Move avaiable to Last\r\n" +
"- Move selected up\r\n" +
"- Move selected down\r\n" +
"- Move selected to First\r\n" +
"- Move selected to Last";
_ = new MessageDialog(content, "What can I Say").ShowAsync();
}

private void ToggleListning_Toggled(object sender, RoutedEventArgs e)
{
if (triggerListning is object)
{
triggerListning.Text = toggleListning.IsOn ? "Voice Off" : "Voice On";
actionListning.Value = !toggleListning.IsOn;
}
}
}
}
Loading