Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto tématu popisujeme příkazy v aplikacích pro Windows. Konkrétně probereme, jak můžete pomocí tříd XamlUICommand a StandardUICommand (společně s rozhraním ICommand) sdílet a spravovat příkazy napříč různými typy ovládacích prvků bez ohledu na použitý typ zařízení a vstupu.
Sdílení příkazů napříč různými ovládacími prvky bez ohledu na typ zařízení a vstupu
Důležitá rozhraní API
Přehled
Příkazy lze vyvolat přímo prostřednictvím interakcí uživatelského rozhraní, jako je kliknutí na tlačítko nebo výběr položky z místní nabídky. Dají se také vyvolat nepřímo prostřednictvím vstupního zařízení, jako je akcelerátor klávesnice, gesto, rozpoznávání řeči nebo nástroj pro automatizaci/přístupnost. Po vyvolání může příkaz zpracovat ovládací prvek (navigace textu v ovládacím prvku pro úpravy), okno (navigace zpět) nebo aplikaci (konec).
Příkazy můžou pracovat s konkrétním kontextem v aplikaci, jako je například odstranění textu nebo vrácení akce zpět, nebo můžou být bez kontextu, například ztlumení zvuku nebo úprava jasu.
Následující obrázek ukazuje dvě rozhraní příkazů ( CommandBar a plovoucí kontextový CommandBarFlyout), která sdílejí některé ze stejných příkazů.
Panel příkazů
Kontextová nabídka v galerii Microsoft Photos
Interakce příkazů
Vzhledem k nejrůznějším zařízením, typům vstupů a povrchům uživatelského rozhraní, které můžou ovlivnit způsob vyvolání příkazu, doporučujeme zpřístupnit vaše příkazy na co nejvíce dostupných místech pro ovládání příkazů. Mezi ně může patřit kombinace potažení prstem, MenuBaru, CommandBaru, CommandBarFlyoutu a tradiční kontextové nabídky.
Pro kritické příkazy použijte akcelerátory specifické pro vstup. Vstupní akcelerátory umožňují uživateli provádět akce rychleji v závislosti na používaném vstupním zařízení.
Tady je několik běžných vstupních akcelerátorů pro různé typy vstupů:
- Ukazatel – tlačítka pro najetí myší a perem
- Klávesnice – Klávesové zkratky (přístupové klávesy a akcelerační klávesy)
- Dotykové ovládání – potáhnutí prstem
- Dotyk – táhněte pro obnovení dat
Pokud chcete, aby funkce vaší aplikace byly všeobecně přístupné, musíte zvážit typ vstupu a uživatelské prostředí. Kolekce (zejména uživatelsky upravitelné) například obvykle obsahují různé konkrétní příkazy, které se provádějí poměrně odlišně v závislosti na vstupním zařízení.
Následující tabulka uvádí některé typické příkazy kolekce a způsoby, jak tyto příkazy zveřejnit.
| Command | Nezávislé na typu vstupu | Akcelerátor myši | Akcelerátor klávesnice | Akcelerátor dotykového ovládání |
|---|---|---|---|---|
| Odstranit položku | Kontextová nabídka | Tlačítko přechodu myší | Klávesa DEL | Přejeďte prstem pro odstranění |
| Označit položku vlajkou | Kontextová nabídka | Tlačítko na najetí myší | Ctrl+Shift+G | Potáhněte prstem pro označení |
| Aktualizace dat | Kontextová nabídka | N/A | Klávesa F5 | Táhněte pro obnovení |
| Přidání položky k oblíbeným položkám | Kontextová nabídka | Tlačítko přechodu myší | F, Ctrl+S | Potáhněte prstem pro přidání k oblíbeným |
Vždy poskytněte místní nabídku Doporučujeme zahrnout všechny relevantní kontextové příkazy v tradiční místní nabídce nebo CommandBarFlyout, protože obě jsou podporovány pro všechny typy vstupů. Pokud je například příkaz vystavený pouze během události najetí ukazatelem myši, nedá se použít na dotykovém zařízení.
Příkazy v aplikacích pro Windows
Existuje několik způsobů, jak sdílet a spravovat příkazové prostředí v aplikaci pro Windows. Můžete definovat obslužné rutiny událostí pro standardní interakce, jako je kliknutí, v kódu na pozadí (to může být poměrně neefektivní v závislosti na složitosti uživatelského rozhraní), můžete svázat naslouchací objekt událostí pro standardní interakce se sdílenou obslužnou rutinou, nebo můžete svázat vlastnost Command ovládacího prvku na implementaci ICommand, která popisuje logiku příkazu.
Pokud chcete poskytovat bohaté a komplexní uživatelské prostředí napříč příkazovými plochami efektivně a s minimální duplikací kódu, doporučujeme používat funkce vazby příkazů popsané v tomto tématu (pro standardní zpracování událostí, viz jednotlivá témata událostí).
Pokud chcete vytvořit vazbu ovládacího prvku na sdílený prostředek příkazu, můžete implementovat rozhraní ICommand sami, nebo můžete sestavit příkaz z xamlUICommand základní třídy nebo jednoho z příkazů platformy definovaných odvozenou třídou StandardUICommand .
- Rozhraní ICommand (Windows.UI.Xaml.Input.ICommand nebo System.Windows.Input.ICommand) umožňuje vytvářet plně přizpůsobené a opakovaně použitelné příkazy v celé aplikaci.
- XamlUICommand také poskytuje tuto funkci, ale zjednodušuje vývoj tím, že zpřístupňuje sadu předdefinovaných vlastností příkazů, jako je chování příkazu, klávesové zkratky (přístupová klávesa a klávesa akcelerátoru), ikona, popisek a popis.
- StandardUICommand zjednodušuje další věci tím, že vám umožní vybrat si ze sady standardních příkazů platformy s předdefinovanými vlastnostmi.
Důležité
V aplikacích pro UPW jsou příkazy implementace rozhraní Windows.UI.Xaml.Input.ICommand (C++) nebo System.Windows.Input.ICommand (C#) v závislosti na zvolené jazykové rozhraní.
Zkušenosti s příkazy pomocí třídy StandardUICommand
Odvozeno z XamlUICommand (odvozené z Windows.UI.Xaml.Input.ICommand pro C++ nebo System.Windows.Input.ICommand pro C#), Třída StandardUICommand zveřejňuje sadu standardních příkazů platformy s předem definovanými vlastnostmi, jako jsou ikona, akcelerátor klávesnice a popis.
StandardUICommand poskytuje rychlý a konzistentní způsob, jak definovat běžné příkazy, jako Save je nebo Delete. Stačí zadat funkce execute a canExecute.
Example
StandardUICommandSample
| Stáhněte si kód pro tento příklad. |
|---|
| Ukázka příkazů UPW (StandardUICommand) |
V tomto příkladu si ukážeme, jak vylepšit základní ListView příkazem Delete item implementovaným prostřednictvím třídy StandardUICommand a současně optimalizovat uživatelské prostředí pro různé typy zadávání pomocí MenuBar, Potáhnutím ovládacího prvku, tlačítka najetí myší a místní nabídky.
Poznámka:
Tato ukázka vyžaduje balíček NuGet Microsoft.UI.Xaml.Controls, který je součástí WinUI 2.
Xaml:
Ukázkové uživatelské rozhraní obsahuje ListView s pěti položkami. Delete StandardUICommand je vázána na MenuBarItem, SwipeItem, AppBarButton a ContextFlyout menu.
<Page
x:Class="StandardUICommandSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:StandardUICommandSample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxcontrols="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<Style x:Key="HorizontalSwipe"
TargetType="ListViewItem"
BasedOn="{StaticResource ListViewItemRevealStyle}">
<Setter Property="Height" Value="60"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
</Page.Resources>
<Grid Loaded="ControlExample_Loaded">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Padding="10"
BorderThickness="0,0,0,1"
BorderBrush="LightBlue"
Background="AliceBlue">
<TextBlock Style="{StaticResource HeaderTextBlockStyle}">
StandardUICommand sample
</TextBlock>
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Margin="0,0,0,10">
This sample shows how to use the StandardUICommand class to
share a platform command and consistent user experiences
across various controls.
</TextBlock>
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Margin="0,0,0,0">
Specifically, we define a standard delete command and add it
to a variety of command surfaces, all of which share a common
icon, label, keyboard accelerator, and description.
</TextBlock>
</StackPanel>
<muxcontrols:MenuBar Grid.Row="1" Padding="10">
<muxcontrols:MenuBarItem Title="File">
</muxcontrols:MenuBarItem>
<muxcontrols:MenuBarItem Title="Edit">
<MenuFlyoutItem x:Name="DeleteFlyoutItem"/>
</muxcontrols:MenuBarItem>
<muxcontrols:MenuBarItem Title="Help">
</muxcontrols:MenuBarItem>
</muxcontrols:MenuBar>
<ListView x:Name="ListViewRight" Grid.Row="2"
Loaded="ListView_Loaded"
IsItemClickEnabled="True"
SelectionMode="Single"
SelectionChanged="ListView_SelectionChanged"
ItemContainerStyle="{StaticResource HorizontalSwipe}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:ListItemData">
<UserControl PointerEntered="ListViewSwipeContainer_PointerEntered"
PointerExited="ListViewSwipeContainer_PointerExited">
<UserControl.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem
Command="{x:Bind Command}"
CommandParameter="{x:Bind Text}" />
</MenuFlyout>
</UserControl.ContextFlyout>
<Grid AutomationProperties.Name="{x:Bind Text}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="HoveringStates">
<VisualState x:Name="HoverButtonsHidden" />
<VisualState x:Name="HoverButtonsShown">
<VisualState.Setters>
<Setter Target="HoverButton.Visibility"
Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SwipeControl x:Name="ListViewSwipeContainer" >
<SwipeControl.RightItems>
<SwipeItems Mode="Execute">
<SwipeItem x:Name="DeleteSwipeItem"
Background="Red"
Command="{x:Bind Command}"
CommandParameter="{x:Bind Text}"/>
</SwipeItems>
</SwipeControl.RightItems>
<Grid VerticalAlignment="Center">
<TextBlock Text="{x:Bind Text}"
Margin="10"
FontSize="18"
HorizontalAlignment="Left"
VerticalAlignment="Center"/>
<AppBarButton x:Name="HoverButton"
IsTabStop="False"
HorizontalAlignment="Right"
Visibility="Collapsed"
Command="{x:Bind Command}"
CommandParameter="{x:Bind Text}"/>
</Grid>
</SwipeControl>
</Grid>
</UserControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
Code-behind
- Nejprve definujeme
ListItemDatatřídu, která obsahuje textový řetězec a ICommand pro každý ListViewItem v našem ListView.
public class ListItemData
{
public String Text { get; set; }
public ICommand Command { get; set; }
}
- Ve třídě MainPage definujeme kolekci
ListItemDataobjektů pro DataTemplateListViewItemTemplate. Potom ho naplníme počáteční kolekcí pěti položek (textem a přidruženým standardUICommand Delete).
/// <summary>
/// ListView item collection.
/// </summary>
ObservableCollection<ListItemData> collection =
new ObservableCollection<ListItemData>();
/// <summary>
/// Handler for the layout Grid control load event.
/// </summary>
/// <param name="sender">Source of the control loaded event</param>
/// <param name="e">Event args for the loaded event</param>
private void ControlExample_Loaded(object sender, RoutedEventArgs e)
{
// Create the standard Delete command.
var deleteCommand = new StandardUICommand(StandardUICommandKind.Delete);
deleteCommand.ExecuteRequested += DeleteCommand_ExecuteRequested;
DeleteFlyoutItem.Command = deleteCommand;
for (var i = 0; i < 5; i++)
{
collection.Add(
new ListItemData {
Text = "List item " + i.ToString(),
Command = deleteCommand });
}
}
/// <summary>
/// Handler for the ListView control load event.
/// </summary>
/// <param name="sender">Source of the control loaded event</param>
/// <param name="e">Event args for the loaded event</param>
private void ListView_Loaded(object sender, RoutedEventArgs e)
{
var listView = (ListView)sender;
// Populate the ListView with the item collection.
listView.ItemsSource = collection;
}
- Dále definujeme zpracovatele ICommand ExecuteRequested, kde implementujeme příkaz pro odstranění položky.
/// <summary>
/// Handler for the Delete command.
/// </summary>
/// <param name="sender">Source of the command event</param>
/// <param name="e">Event args for the command event</param>
private void DeleteCommand_ExecuteRequested(
XamlUICommand sender, ExecuteRequestedEventArgs args)
{
// If possible, remove specified item from collection.
if (args.Parameter != null)
{
foreach (var i in collection)
{
if (i.Text == (args.Parameter as string))
{
collection.Remove(i);
return;
}
}
}
if (ListViewRight.SelectedIndex != -1)
{
collection.RemoveAt(ListViewRight.SelectedIndex);
}
}
- Nakonec definujeme obslužné rutiny pro různé události ListView, včetně pointerEntered, PointerExited a SelectionChanged událostí. Obslužné rutiny událostí ukazatele slouží k zobrazení nebo skrytí tlačítka Odstranit pro každou položku.
/// <summary>
/// Handler for the ListView selection changed event.
/// </summary>
/// <param name="sender">Source of the selection changed event</param>
/// <param name="e">Event args for the selection changed event</param>
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListViewRight.SelectedIndex != -1)
{
var item = collection[ListViewRight.SelectedIndex];
}
}
/// <summary>
/// Handler for the pointer entered event.
/// Displays the delete item "hover" buttons.
/// </summary>
/// <param name="sender">Source of the pointer entered event</param>
/// <param name="e">Event args for the pointer entered event</param>
private void ListViewSwipeContainer_PointerEntered(
object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType ==
Windows.Devices.Input.PointerDeviceType.Mouse ||
e.Pointer.PointerDeviceType ==
Windows.Devices.Input.PointerDeviceType.Pen)
{
VisualStateManager.GoToState(
sender as Control, "HoverButtonsShown", true);
}
}
/// <summary>
/// Handler for the pointer exited event.
/// Hides the delete item "hover" buttons.
/// </summary>
/// <param name="sender">Source of the pointer exited event</param>
/// <param name="e">Event args for the pointer exited event</param>
private void ListViewSwipeContainer_PointerExited(
object sender, PointerRoutedEventArgs e)
{
VisualStateManager.GoToState(
sender as Control, "HoverButtonsHidden", true);
}
Prostředí příkazů s využitím třídy XamlUICommand
Pokud potřebujete vytvořit příkaz, který není definovaný třídou StandardUICommand nebo chcete mít větší kontrolu nad vzhledem příkazu, třída XamlUICommand je odvozena z rozhraní ICommand a přidává různé vlastnosti uživatelského rozhraní (například ikonu, popisek, popis a klávesové zkratky), metody a události pro rychlé definování uživatelského rozhraní a chování vlastního příkazu.
XamlUICommand umožňuje zadat uživatelské rozhraní prostřednictvím řídicí vazby, jako je ikona, popisek, popis a klávesové zkratky (přístupová klávesa i akcelerátor klávesnice), aniž byste nastavili jednotlivé vlastnosti.
Example
XamlUICommandSample
| Stáhněte si kód pro tento příklad. |
|---|
| Ukázka příkazů UPW (XamlUICommand) |
Tento příklad sdílí funkce Delete z předchozího příkladu StandardUICommand , ale ukazuje, jak xamlUICommand třída umožňuje definovat vlastní příkaz delete s vlastní ikonou písma, popiskem, akcelerátorem klávesnice a popisem. Podobně jako v příkladu StandardUICommand vylepšujeme základní ListView příkazem Delete item implementovaným prostřednictvím třídy XamlUICommand a současně optimalizujeme uživatelské prostředí pro různé typy zadávání pomocí řádku nabídek, ovládacího prvku Potáhnutí prstem , tlačítek najetí myší a kontextové nabídky.
Mnoho ovládacích prvků platformy používá vlastnosti XamlUICommand na pozadí, stejně jako v našem příkladu se StandardUICommand v předchozí části.
Poznámka:
Tato ukázka vyžaduje balíček NuGet Microsoft.UI.Xaml.Controls, který je součástí WinUI 2.
Xaml:
Ukázkové uživatelské rozhraní obsahuje ListView s pěti položkami. Vlastní XamlUICommand CustomXamlUICommand je vázán na MenuBarItem, SwipeItem, AppBarButton a ContextFlyout menu.
<Page
x:Class="XamlUICommand_Sample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlUICommand_Sample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxcontrols="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<XamlUICommand x:Name="CustomXamlUICommand"
ExecuteRequested="DeleteCommand_ExecuteRequested"
Description="Custom XamlUICommand"
Label="Custom XamlUICommand">
<XamlUICommand.IconSource>
<FontIconSource FontFamily="Wingdings" Glyph="M"/>
</XamlUICommand.IconSource>
<XamlUICommand.KeyboardAccelerators>
<KeyboardAccelerator Key="D" Modifiers="Control"/>
</XamlUICommand.KeyboardAccelerators>
</XamlUICommand>
<Style x:Key="HorizontalSwipe"
TargetType="ListViewItem"
BasedOn="{StaticResource ListViewItemRevealStyle}">
<Setter Property="Height" Value="70"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
</Page.Resources>
<Grid Loaded="ControlExample_Loaded" Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Padding="10"
BorderThickness="0,0,0,1"
BorderBrush="LightBlue"
Background="AliceBlue">
<TextBlock Style="{StaticResource HeaderTextBlockStyle}">
XamlUICommand sample
</TextBlock>
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Margin="0,0,0,10">
This sample shows how to use the XamlUICommand class to
share a custom command with consistent user experiences
across various controls.
</TextBlock>
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Margin="0,0,0,0">
Specifically, we define a custom delete command and add it
to a variety of command surfaces, all of which share a common
icon, label, keyboard accelerator, and description.
</TextBlock>
</StackPanel>
<muxcontrols:MenuBar Grid.Row="1">
<muxcontrols:MenuBarItem Title="File">
</muxcontrols:MenuBarItem>
<muxcontrols:MenuBarItem Title="Edit">
<MenuFlyoutItem x:Name="DeleteFlyoutItem"
Command="{StaticResource CustomXamlUICommand}"/>
</muxcontrols:MenuBarItem>
<muxcontrols:MenuBarItem Title="Help">
</muxcontrols:MenuBarItem>
</muxcontrols:MenuBar>
<ListView x:Name="ListViewRight" Grid.Row="2"
Loaded="ListView_Loaded"
IsItemClickEnabled="True"
SelectionMode="Single"
SelectionChanged="ListView_SelectionChanged"
ItemContainerStyle="{StaticResource HorizontalSwipe}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:ListItemData">
<UserControl PointerEntered="ListViewSwipeContainer_PointerEntered"
PointerExited="ListViewSwipeContainer_PointerExited">
<UserControl.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem
Command="{x:Bind Command}"
CommandParameter="{x:Bind Text}" />
</MenuFlyout>
</UserControl.ContextFlyout>
<Grid AutomationProperties.Name="{x:Bind Text}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="HoveringStates">
<VisualState x:Name="HoverButtonsHidden" />
<VisualState x:Name="HoverButtonsShown">
<VisualState.Setters>
<Setter Target="HoverButton.Visibility"
Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SwipeControl x:Name="ListViewSwipeContainer">
<SwipeControl.RightItems>
<SwipeItems Mode="Execute">
<SwipeItem x:Name="DeleteSwipeItem"
Background="Red"
Command="{x:Bind Command}"
CommandParameter="{x:Bind Text}"/>
</SwipeItems>
</SwipeControl.RightItems>
<Grid VerticalAlignment="Center">
<TextBlock Text="{x:Bind Text}"
Margin="10"
FontSize="18"
HorizontalAlignment="Left"
VerticalAlignment="Center"/>
<AppBarButton x:Name="HoverButton"
IsTabStop="False"
HorizontalAlignment="Right"
Visibility="Collapsed"
Command="{x:Bind Command}"
CommandParameter="{x:Bind Text}"/>
</Grid>
</SwipeControl>
</Grid>
</UserControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
Kód na pozadí
- Nejprve definujeme
ListItemDatatřídu, která obsahuje textový řetězec a ICommand pro každý ListViewItem v našem ListView.
public class ListItemData
{
public String Text { get; set; }
public ICommand Command { get; set; }
}
- Ve třídě MainPage definujeme kolekci
ListItemDataobjektů pro DataTemplateListViewItemTemplate. Potom ho naplníme počáteční kolekcí pěti položek (s textem a přidruženým XamlUICommand).
ObservableCollection<ListItemData> collection = new ObservableCollection<ListItemData>();
private void ControlExample_Loaded(object sender, RoutedEventArgs e)
{
for (var i = 0; i < 5; i++)
{
collection.Add(
new ListItemData { Text = "List item " + i.ToString(), Command = CustomXamlUICommand });
}
}
private void ListView_Loaded(object sender, RoutedEventArgs e)
{
var listView = (ListView)sender;
listView.ItemsSource = collection;
}
- Dále definujeme obslužnou rutinu ICommand ExecuteRequested, kde implementujeme příkaz pro odstranění položky.
private void DeleteCommand_ExecuteRequested(
XamlUICommand sender, ExecuteRequestedEventArgs args)
{
if (args.Parameter != null)
{
foreach (var i in collection)
{
if (i.Text == (args.Parameter as string))
{
collection.Remove(i);
return;
}
}
}
if (ListViewRight.SelectedIndex != -1)
{
collection.RemoveAt(ListViewRight.SelectedIndex);
}
}
- Nakonec definujeme obslužné rutiny pro různé události ListView, včetně pointerEntered, PointerExited a SelectionChanged událostí. Obslužné rutiny událostí ukazatele slouží k zobrazení nebo skrytí tlačítka Odstranit pro každou položku.
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListViewRight.SelectedIndex != -1)
{
var item = collection[ListViewRight.SelectedIndex];
}
}
private void ListViewSwipeContainer_PointerEntered(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType ==
Windows.Devices.Input.PointerDeviceType.Mouse ||
e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Pen)
{
VisualStateManager.GoToState(sender as Control, "HoverButtonsShown", true);
}
}
private void ListViewSwipeContainer_PointerExited(object sender, PointerRoutedEventArgs e)
{
VisualStateManager.GoToState(sender as Control, "HoverButtonsHidden", true);
}
Zkušenosti s příkazy pomocí rozhraní ICommand
Standardní ovládací prvky UPW (tlačítko, seznam, výběr, kalendář, prediktivní text) poskytují základ pro řadu běžných příkazů. Úplný seznam typů ovládacích prvků najdete v tématu Ovládací prvky a vzory pro aplikace pro Windows.
Nejzákladnější způsob, jak podporovat prostředí strukturovaných příkazů, je definovat implementaci rozhraní ICommand (Windows.UI.Xaml.Input.ICommand pro C++ nebo System.Windows.Input.ICommand pro C#). Tato instance ICommand se pak může svázat s ovládacími prvky, jako jsou tlačítka.
Poznámka:
V některých případech může být stejně efektivní vytvořit vazbu metody na událost Click a vlastnosti na vlastnost JePovoleno.
Example
Příklad ICommand
| Stáhněte si kód pro tento příklad. |
|---|
| Ukázka příkazů UPW (ICommand) |
V tomto základním příkladu si ukážeme, jak lze vyvolat jeden příkaz kliknutím na tlačítko, akcelerátorem klávesnice a otočením kolečka myši.
Používáme dva Objekty ListView, jednu naplněnou pěti položkami a druhou prázdnou a dvě tlačítka, jedno pro přesouvání položek z ListView vlevo do Objektu ListView vpravo a druhý pro přesouvání položek zprava doleva. Každé tlačítko je vázané na odpovídající příkaz (ViewModel.MoveRightCommand a ViewModel.MoveLeftCommand, v uvedeném pořadí) a jsou povoleny a zakázány automaticky na základě počtu položek v jejich přidruženém Objektu ListView.
Následující kód XAML definuje uživatelské rozhraní pro náš příklad.
<Page
x:Class="UICommand1.View.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:UICommand1.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<vm:OpacityConverter x:Key="opaque" />
</Page.Resources>
<Grid Name="ItemGrid"
Background="AliceBlue"
PointerWheelChanged="Page_PointerWheelChanged">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListView Grid.Column="0" VerticalAlignment="Center"
x:Name="CommandListView"
ItemsSource="{x:Bind Path=ViewModel.ListItemLeft}"
SelectionMode="None" IsItemClickEnabled="False"
HorizontalAlignment="Right">
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:ListItemData">
<Grid VerticalAlignment="Center">
<AppBarButton Label="{x:Bind ListItemText}">
<AppBarButton.Icon>
<SymbolIcon Symbol="{x:Bind ListItemIcon}"/>
</AppBarButton.Icon>
</AppBarButton>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Grid Grid.Column="1" Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="1">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="40" Glyph=""
Opacity="{x:Bind Path=ViewModel.ListItemLeft.Count,
Mode=OneWay, Converter={StaticResource opaque}}"/>
<Button Name="MoveItemRightButton"
Margin="0,10,0,10" Width="120" HorizontalAlignment="Center"
Command="{x:Bind Path=ViewModel.MoveRightCommand}">
<Button.KeyboardAccelerators>
<KeyboardAccelerator
Modifiers="Control"
Key="Add" />
</Button.KeyboardAccelerators>
<StackPanel>
<SymbolIcon Symbol="Next"/>
<TextBlock>Move item right</TextBlock>
</StackPanel>
</Button>
<Button Name="MoveItemLeftButton"
Margin="0,10,0,10" Width="120" HorizontalAlignment="Center"
Command="{x:Bind Path=ViewModel.MoveLeftCommand}">
<Button.KeyboardAccelerators>
<KeyboardAccelerator
Modifiers="Control"
Key="Subtract" />
</Button.KeyboardAccelerators>
<StackPanel>
<SymbolIcon Symbol="Previous"/>
<TextBlock>Move item left</TextBlock>
</StackPanel>
</Button>
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}"
FontSize="40" Glyph=""
Opacity="{x:Bind Path=ViewModel.ListItemRight.Count,
Mode=OneWay, Converter={StaticResource opaque}}"/>
</StackPanel>
</Grid>
<ListView Grid.Column="2"
x:Name="CommandListViewRight"
VerticalAlignment="Center"
IsItemClickEnabled="False"
SelectionMode="None"
ItemsSource="{x:Bind Path=ViewModel.ListItemRight}"
HorizontalAlignment="Left">
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:ListItemData">
<Grid VerticalAlignment="Center">
<AppBarButton Label="{x:Bind ListItemText}">
<AppBarButton.Icon>
<SymbolIcon Symbol="{x:Bind ListItemIcon}"/>
</AppBarButton.Icon>
</AppBarButton>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
Tady je kód pro předchozí uživatelské rozhraní.
V kódu na pozadí se připojíme k našemu modelu zobrazení, který obsahuje náš příkazový kód. Kromě toho definujeme obslužnou rutinu pro vstup z kolečka myši, který také spojuje náš kód příkazu.
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Controls;
using UICommand1.ViewModel;
using Windows.System;
using Windows.UI.Core;
namespace UICommand1.View
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
// Reference to our view model.
public UICommand1ViewModel ViewModel { get; set; }
// Initialize our view and view model.
public MainPage()
{
this.InitializeComponent();
ViewModel = new UICommand1ViewModel();
}
/// <summary>
/// Handle mouse wheel input and assign our
/// commands to appropriate direction of rotation.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Page_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
var props = e.GetCurrentPoint(sender as UIElement).Properties;
// Require CTRL key and accept only vertical mouse wheel movement
// to eliminate accidental wheel input.
if ((Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) !=
CoreVirtualKeyStates.None) && !props.IsHorizontalMouseWheel)
{
bool delta = props.MouseWheelDelta < 0 ? true : false;
switch (delta)
{
case true:
ViewModel.MoveRight();
break;
case false:
ViewModel.MoveLeft();
break;
default:
break;
}
}
}
}
}
Tady je kód z našeho modelu zobrazení.
Náš model zobrazení je místo, kde definujeme podrobnosti o spuštění pro dva příkazy v naší aplikaci, naplníme jeden ListView a poskytneme převaděč hodnot neprůhlednosti pro skrytí nebo zobrazení nějakého dalšího uživatelského rozhraní na základě počtu položek každého ListView.
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
namespace UICommand1.ViewModel
{
/// <summary>
/// UI properties for our list items.
/// </summary>
public class ListItemData
{
/// <summary>
/// Gets and sets the list item content string.
/// </summary>
public string ListItemText { get; set; }
/// <summary>
/// Gets and sets the list item icon.
/// </summary>
public Symbol ListItemIcon { get; set; }
}
/// <summary>
/// View Model that sets up a command to handle invoking the move item buttons.
/// </summary>
public class UICommand1ViewModel
{
/// <summary>
/// The command to invoke when the Move item left button is pressed.
/// </summary>
public RelayCommand MoveLeftCommand { get; private set; }
/// <summary>
/// The command to invoke when the Move item right button is pressed.
/// </summary>
public RelayCommand MoveRightCommand { get; private set; }
// Item collections
public ObservableCollection<ListItemData> ListItemLeft { get; } =
new ObservableCollection<ListItemData>();
public ObservableCollection<ListItemData> ListItemRight { get; } =
new ObservableCollection<ListItemData>();
public ListItemData listItem;
/// <summary>
/// Sets up a command to handle invoking the move item buttons.
/// </summary>
public UICommand1ViewModel()
{
MoveLeftCommand =
new RelayCommand(new Action(MoveLeft), CanExecuteMoveLeftCommand);
MoveRightCommand =
new RelayCommand(new Action(MoveRight), CanExecuteMoveRightCommand);
LoadItems();
}
/// <summary>
/// Populate our list of items.
/// </summary>
public void LoadItems()
{
for (var x = 0; x <= 4; x++)
{
listItem = new ListItemData();
listItem.ListItemText = "Item " + (ListItemLeft.Count + 1).ToString();
listItem.ListItemIcon = Symbol.Emoji;
ListItemLeft.Add(listItem);
}
}
/// <summary>
/// Move left command valid when items present in the list on right.
/// </summary>
/// <returns>True, if count is greater than 0.</returns>
private bool CanExecuteMoveLeftCommand()
{
return ListItemRight.Count > 0;
}
/// <summary>
/// Move right command valid when items present in the list on left.
/// </summary>
/// <returns>True, if count is greater than 0.</returns>
private bool CanExecuteMoveRightCommand()
{
return ListItemLeft.Count > 0;
}
/// <summary>
/// The command implementation to execute when the Move item right button is pressed.
/// </summary>
public void MoveRight()
{
if (ListItemLeft.Count > 0)
{
listItem = new ListItemData();
ListItemRight.Add(listItem);
listItem.ListItemText = "Item " + ListItemRight.Count.ToString();
listItem.ListItemIcon = Symbol.Emoji;
ListItemLeft.RemoveAt(ListItemLeft.Count - 1);
MoveRightCommand.RaiseCanExecuteChanged();
MoveLeftCommand.RaiseCanExecuteChanged();
}
}
/// <summary>
/// The command implementation to execute when the Move item left button is pressed.
/// </summary>
public void MoveLeft()
{
if (ListItemRight.Count > 0)
{
listItem = new ListItemData();
ListItemLeft.Add(listItem);
listItem.ListItemText = "Item " + ListItemLeft.Count.ToString();
listItem.ListItemIcon = Symbol.Emoji;
ListItemRight.RemoveAt(ListItemRight.Count - 1);
MoveRightCommand.RaiseCanExecuteChanged();
MoveLeftCommand.RaiseCanExecuteChanged();
}
}
/// <summary>
/// Views subscribe to this event to get notified of property updates.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notify subscribers of updates to the named property
/// </summary>
/// <param name="propertyName">The full, case-sensitive, name of a property.</param>
protected void NotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
PropertyChangedEventArgs args = new PropertyChangedEventArgs(propertyName);
handler(this, args);
}
}
}
/// <summary>
/// Convert a collection count to an opacity value of 0.0 or 1.0.
/// </summary>
public class OpacityConverter : IValueConverter
{
/// <summary>
/// Converts a collection count to an opacity value of 0.0 or 1.0.
/// </summary>
/// <param name="value">The count passed in</param>
/// <param name="targetType">Ignored.</param>
/// <param name="parameter">Ignored</param>
/// <param name="language">Ignored</param>
/// <returns>1.0 if count > 0, otherwise returns 0.0</returns>
public object Convert(object value, Type targetType, object parameter, string language)
{
return ((int)value > 0 ? 1.0 : 0.0);
}
/// <summary>
/// Not used, converter is not intended for two-way binding.
/// </summary>
/// <param name="value">Ignored</param>
/// <param name="targetType">Ignored</param>
/// <param name="parameter">Ignored</param>
/// <param name="language">Ignored</param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}
A konečně, zde je naše implementace ICommand rozhraní
Zde definujeme příkaz, který implementuje rozhraní ICommand a jednoduše předává jeho funkce jiným objektům.
using System;
using System.Windows.Input;
namespace UICommand1
{
/// <summary>
/// A command whose sole purpose is to relay its functionality
/// to other objects by invoking delegates.
/// The default return value for the CanExecute method is 'true'.
/// <see cref="RaiseCanExecuteChanged"/> needs to be called whenever
/// <see cref="CanExecute"/> is expected to return a different value.
/// </summary>
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
/// <summary>
/// Raised when RaiseCanExecuteChanged is called.
/// </summary>
public event EventHandler CanExecuteChanged;
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action execute, Func<bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
/// <summary>
/// Determines whether this <see cref="RelayCommand"/> can execute in its current state.
/// </summary>
/// <param name="parameter">
/// Data used by the command. If the command does not require
/// data to be passed, this object can be set to null.
/// </param>
/// <returns>true if this command can be executed; otherwise, false.</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute();
}
/// <summary>
/// Executes the <see cref="RelayCommand"/> on the current command target.
/// </summary>
/// <param name="parameter">
/// Data used by the command. If the command does not require
/// data to be passed, this object can be set to null.
/// </param>
public void Execute(object parameter)
{
_execute();
}
/// <summary>
/// Method used to raise the <see cref="CanExecuteChanged"/> event
/// to indicate that the return value of the <see cref="CanExecute"/>
/// method has changed.
/// </summary>
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
}
Shrnutí
Univerzální platforma Windows poskytuje robustní a flexibilní systém příkazů, který umožňuje vytvářet aplikace, které sdílejí a spravují příkazy napříč typy ovládacích prvků, zařízeními a vstupními typy.
Při vytváření příkazů pro aplikace pro Windows použijte následující přístupy:
- Naslouchání a zpracování událostí ve XAML a v souvisejícím kódu
- Vázání na metodu zpracování událostí, jako je Click
- Definování vlastní implementace ICommand
- Vytvoření objektů XamlUICommand s vlastními hodnotami pro předem definovanou sadu vlastností
- Vytvoření objektů StandardUICommand se sadou předdefinovaných vlastností a hodnot platformy
Další kroky
Úplný příklad znázorňuje implementaci XamlUICommand a StandardUICommand , viz ukázka galerie WinUI 2 .
Viz také
Ovládací prvky a vzory pro aplikace pro Windows
Samples
Ukázky témat
- Ukázka příkazů UPW (StandardUICommand)
- Ukázka příkazů UPW (XamlUICommand)
- Ukázka příkazů UPW (ICommand)
Další ukázky
Windows developer