Skip to content

Commit

Permalink
feat: ControlExtensions and InputExtensions (#287)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiaoy312 committed Aug 24, 2022
1 parent 66a26ed commit cdd407c
Show file tree
Hide file tree
Showing 11 changed files with 509 additions and 1 deletion.
2 changes: 2 additions & 0 deletions doc/controls-styles.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ The `Uno.Toolkit.UI` library adds the following controls:
The `Uno.Toolkit.UI` library adds the following helper classes:
- `SystemThemeHelper`: Provides a set of helper methods to check the current operating system theme, and manipulate the application dark/light theme.
- [`AncestorBinding` and `ItemsControlBinding`](helpers\ancestor-itemscontrol-binding.md): These markup extensions provides relative binding based on ancestor type. If you are familiar with WPF, they are very similar to `{RelativeSource Mode=FindAncestor}`.
- [`ControlExtensions`](helpers\control-extensions.md): Provides various attached properties for common controls.
- [`InputExtensions`](helpers\input-extensions.md): Provides various attached properties for _input controls_, such as `TextBox` and `PasswordBox`.
- [`StatusBar`](helpers\StatusBar-extensions.md): Provides two attached properties on `Page` to controls the visual of the status bar on mobile platforms.

## Control Styles
Expand Down
28 changes: 28 additions & 0 deletions doc/helpers/Input-extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# InputExtensions Attached Properties
Provides various attached properties for _input controls_, such as `TextBox` and `PasswordBox`.

## Properties
Property|Type|Description
-|-|-
AutoDismiss|bool|Whether the soft-keyboard will be dismissed when the enter key is pressed.
AutoFocusNext|bool|Whether the focus will move to the next focusable element when the enter key is pressed.\*
AutoFocusNextElement|Control|Sets the next control to focus when the enter key is pressed.\*

AutoFocusNext and AutoFocusNextElement\*: Having either or both of the two properties set will enable the focus next behavior. AutoFocusNextElement will take precedences over AutoFocusNext when both are set.

### Remarks
- AutoFocusNext and AutoFocusNextElement have different focus target:
- AutoFocusNext is determined by `FocusManager.FindNextFocusableElement`
- AutoFocusNextElement is provided by the value.

## Usage
```xml
<!-- The focus will move in this order when pressing enter repeatedly: 1-2-4-3 -->
<TextBox x:Name="Input1" utu:InputExtensions.AutoFocusNext="True" />
<TextBox x:Name="Input2" utu:InputExtensions.AutoFocusNextElement="{Binding ElementName=Input4}" />
<TextBox x:Name="Input3" utu:InputExtensions.AutoFocusNextElement="{Binding ElementName=Input1}" />
<TextBox x:Name="Input4" utu:InputExtensions.AutoFocusNextElement="{Binding ElementName=Input3}" />

<!-- Dismiss soft-keyboard on enter -->
<TextBox utu:InputExtensions.AutoDismiss="True" />
```
39 changes: 39 additions & 0 deletions doc/helpers/control-extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ControlExtensions Attached Properties
Provides various attached properties for common controls.

## Properties
Property|Type|Description
-|-|-
Command|ICommand|Sets the command to execute for: <br>- `TextBox`/`PasswordBox` enter key press\*<br>- `ListView` item click\*<br>- `NavigationView` item click
CommandParameter|ICommand|Sets the parameter to pass to the Command property.

Command on `TextBox`/`PasswordBox`\*: Having this set will also cause the keyboard dismiss on enter.
Command on `ListView`\*: [`IsItemClickEnabled`](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.listviewbase.isitemclickenabled) must also be set to true for this to work.

### Remarks
- For Command, the relevant parameter is also provided for the `CanExecute` and `Execute` call:
> Unless CommandParameter is set, which replaces the following.
- `TextBox.Text`
- `PasswordBox.Password`
- `ItemClickEventArgs.ClickedItem` from `ListView.ItemClick`
- `NavigationViewItemInvokedEventArgs.InvokedItem` from `NavigationView.ItemInvoked`

## Usage
```xml
<!-- Execute command on enter -->
<PasswordBox utu:ControlExtensions.Command="{Binding Login}" />

<!-- ListView item click-->
<ListView ItemsSource="123"
IsItemClickEnabled="True"
utu:ControlExtensions.Command="{Binding UpdateSelection}" />

<!-- NavigationView item invoke -->
<NavigationView utu:ControlExtensions.Command="{Binding Navigate}">
<NavigationView.MenuItems>
<NavigationViewItem Content="Apple" />
<NavigationViewItem Content="Banana" />
<NavigationViewItem Content="Cactus" />
</NavigationView.MenuItems>
</NavigationView>
```
4 changes: 4 additions & 0 deletions doc/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
items:
- name: AncestorBinding and ItemsControlBinding
href: helpers/ancestor-itemscontrol-binding.md
- name: ControlExtensions attached properties
href: helpers/control-extensions.md
- name: InputExtensions attached properties
href: helpers/input-extensions.md
- name: StatusBar attached properties
href: helpers/StatusBar-extensions.md
# ***************** Styles **********************
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<Page x:Class="Uno.Toolkit.Samples.Content.Controls.ControlExtensionsSamplePage"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:Uno.UI.Toolkit"
xmlns:sample="using:Uno.Toolkit.Samples"
xmlns:utu="using:Uno.Toolkit.UI"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">


<Grid Background="{ThemeResource SurfaceBrush}">
<sample:SamplePageLayout x:Name="SamplePageLayout" IsDesignAgnostic="True">
<sample:SamplePageLayout.DesignAgnosticTemplate>
<DataTemplate>
<StackPanel DataContext="{Binding Data}" Spacing="20">
<TextBlock>The Command attached property allows an ICommand to be associated to:</TextBlock>

<!-- Text/PasswordBox[Command] example -->
<StackPanel Spacing="8">
<TextBlock Text="- TextBox/PasswordBox enter key press:" />
<TextBlock Text="{Binding InputDebugText}" />
<TextBox utu:ControlExtensions.Command="{Binding DebugInputCommand}" />
</StackPanel>

<!-- ListView[Command] example -->
<StackPanel Spacing="8">
<TextBlock Text="- ListView item click:" />
<TextBlock Text="{Binding SelectionDebugText}" />
<ListView ItemsSource="123"
IsItemClickEnabled="True"
utu:ControlExtensions.Command="{Binding DebugSelectionCommand}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock>Item #<Run Text="{Binding}" /></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>

<!-- NavigationView[Command] example -->
<StackPanel>
<TextBlock Text="- NavigationView item invoke" />
<TextBlock Text="{Binding NavigationDebugText}" />
<NavigationView utu:ControlExtensions.Command="{Binding DebugNavigationCommand}">
<NavigationView.MenuItems>
<NavigationViewItem Content="Apple" />
<NavigationViewItem Content="Banana" />
<NavigationViewItem Content="Cactus" />
</NavigationView.MenuItems>
</NavigationView>
</StackPanel>

</StackPanel>
</DataTemplate>
</sample:SamplePageLayout.DesignAgnosticTemplate>
</sample:SamplePageLayout>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Windows.Input;
using Uno.Toolkit.Samples.Entities;
using Uno.Toolkit.Samples.ViewModels;
using Uno.Toolkit.UI;
using static System.FormattableString;

#if IS_WINUI
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#endif

namespace Uno.Toolkit.Samples.Content.Controls
{
[SamplePage(SampleCategory.Behaviors, nameof(ControlExtensions), SourceSdk.UnoToolkit, DataType = typeof(ControlExtensionsSamplePageVM))]
public sealed partial class ControlExtensionsSamplePage : Page
{
public ControlExtensionsSamplePage()
{
this.InitializeComponent();
}

public class ControlExtensionsSamplePageVM : ViewModelBase
{
public string InputDebugText { get => GetProperty<string>(); set => SetProperty(value); }
public string SelectionDebugText { get => GetProperty<string>(); set => SetProperty(value); }
public string NavigationDebugText { get => GetProperty<string>(); set => SetProperty(value); }

public ICommand DebugInputCommand => new Command(DebugInput);
public ICommand DebugSelectionCommand => new Command(DebugSelection);
public ICommand DebugNavigationCommand => new Command(DebugNavigation);

private void DebugInput(object parameter) => InputDebugText = Invariant($"{DateTime.Now:HH:mm:ss}: parameter={parameter}");
private void DebugSelection(object parameter) => SelectionDebugText = Invariant($"{DateTime.Now:HH:mm:ss}: parameter={parameter}");
private void DebugNavigation(object parameter) => NavigationDebugText = Invariant($"{DateTime.Now:HH:mm:ss}: parameter={parameter}");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<Page x:Class="Uno.Toolkit.Samples.Content.Controls.InputExtensionsSamplePage"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:Uno.UI.Toolkit"
xmlns:sample="using:Uno.Toolkit.Samples"
xmlns:utu="using:Uno.Toolkit.UI"
mc:Ignorable="d">

<Grid Background="{ThemeResource SurfaceBrush}">
<sample:SamplePageLayout x:Name="SamplePageLayout" IsDesignAgnostic="True">
<sample:SamplePageLayout.DesignAgnosticTemplate>
<DataTemplate>
<StackPanel Spacing="40">

<StackPanel Spacing="8">
<TextBlock Text="AutoFocusNext and AutoFocusNextElement can be used to move focus on enter." />
<TextBox x:Name="Input1"
Text="Input1 (focus next)"
utu:InputExtensions.AutoFocusNext="True" />
<TextBox x:Name="Input2"
Text="Input2 (focus Input4)"
utu:InputExtensions.AutoFocusNextElement="{Binding ElementName=Input4}" />
<TextBox x:Name="Input3"
Text="Input3 (focus Input1)"
utu:InputExtensions.AutoFocusNextElement="{Binding ElementName=Input1}" />
<TextBox x:Name="Input4"
Text="Input4 (focus Input3)"
utu:InputExtensions.AutoFocusNextElement="{Binding ElementName=Input3}" />
</StackPanel>

<StackPanel Spacing="8">
<TextBlock Text="Dismiss soft-keyboard on enter" />
<TextBox utu:InputExtensions.AutoDismiss="True" />
</StackPanel>

</StackPanel>
</DataTemplate>
</sample:SamplePageLayout.DesignAgnosticTemplate>
</sample:SamplePageLayout>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Linq;
using System.Windows.Input;
using Uno.Toolkit.Samples.Entities;
using Uno.Toolkit.Samples.ViewModels;
using Uno.Toolkit.UI;

#if IS_WINUI
using Microsoft.UI.Xaml.Controls;
#else
using Windows.UI.Xaml.Controls;
#endif

namespace Uno.Toolkit.Samples.Content.Controls
{
[SamplePage(SampleCategory.Behaviors, nameof(InputExtensions), SourceSdk.UnoToolkit)]
public sealed partial class InputExtensionsSamplePage : Page
{
public InputExtensionsSamplePage()
{
this.InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
Expand All @@ -25,10 +25,16 @@
<Compile Include="$(MSBuildThisFileDirectory)Content\Controls\ChipSamplePage.xaml.cs">
<DependentUpon>ChipSamplePage.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Content\Controls\ControlExtensionsSamplePage.xaml.cs">
<DependentUpon>ControlExtensionsSamplePage.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Content\Controls\DrawerFlyoutSamplePage.xaml.cs">
<DependentUpon>DrawerFlyoutSamplePage.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Content\Controls\IExitNestedSampleHandler.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Content\Controls\InputExtensionsSamplePage.xaml.cs">
<DependentUpon>InputExtensionsSamplePage.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Content\Controls\StatusBarSamplePage.xaml.cs">
<DependentUpon>StatusBarSamplePage.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -150,6 +156,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Content\Controls\ControlExtensionsSamplePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Content\Controls\DividerSamplePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand All @@ -166,6 +176,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Content\Controls\InputExtensionsSamplePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Content\Controls\StatusBarSamplePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down
Loading

0 comments on commit cdd407c

Please sign in to comment.