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 @@ -356,6 +356,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 @@ -544,6 +545,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 @@ -584,6 +590,8 @@
<Content Include="SamplePages\AutoFocusBehavior\AutoFocusBehaviorXaml.bind" />
<Content Include="SamplePages\ColorPicker\ColorPickerXaml.bind" />
<Content Include="SamplePages\ColorPicker\ColorPickerButtonXaml.bind" />
<Content Include="SamplePages\VoiceCommands\VoiceCommandsPageXaml.bind" />
<Content Include="SamplePages\VoiceCommands\VoiceCommandsPageCode.bind" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
Expand Down Expand Up @@ -1327,6 +1335,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,23 @@
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,52 @@
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,172 @@
<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">

<Interactivity:Interaction.Behaviors>
<Behaviors:VoiceCommandTrigger IsEnabled="{x:Bind toggleListning.IsOn, Mode=OneWay}"
Text="What can I say">
<core:CallMethodAction MethodName="WhatCanISay"
TargetObject="{x:Bind pageRoot}" />
</Behaviors:VoiceCommandTrigger>
</Interactivity:Interaction.Behaviors>

<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>

<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,81 @@
using System;
using Microsoft.Toolkit.Uwp.UI.Behaviors;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

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()
{
_ = new MessageDialog("TODO: 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