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.
Mnoho aplikací obsahuje kolekce obsahu ve formě seznamů, mřížek a stromů, se kterými můžou uživatelé manipulovat. Uživatelé můžou například odstranit, přejmenovat, označit příznakem nebo aktualizovat položky. V tomto článku se dozvíte, jak pomocí kontextových příkazů implementovat tyto druhy akcí způsobem, který poskytuje nejlepší možné prostředí pro všechny typy vstupů.
Důležitá rozhraní API: ICommand interface, UIElement.ContextFlyout – vlastnost, INotifyPropertyChanged rozhraní
Vytváření příkazů pro všechny vstupní typy
Vzhledem k tomu, že uživatelé můžou pracovat s aplikací pro Windows pomocí široké škály zařízení a vstupů, měla by vaše aplikace zobrazovat příkazy jak prostřednictvím kontextových nabídek nezávislých na vstupu, tak i přesto vstupně specifické zkratky. Zahrnutím obou umožňuje uživateli rychle vyvolat příkazy v obsahu bez ohledu na typ vstupu nebo zařízení.
Tato tabulka ukazuje 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 přechodu 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 |
Obecně byste měli všechny příkazy pro položku zpřístupnit v místní nabídce položky. Místní nabídky jsou přístupné uživatelům bez ohledu na typ vstupu a měly by obsahovat všechny příslušné příkazy v daném kontextu, které může uživatel provést.
U často přístupných příkazů zvažte použití vstupních akcelerátorů. Vstupní akcelerátory umožňují uživateli rychle provádět akce na základě svého vstupního zařízení. Mezi vstupní akcelerátory patří:
- Potáhnutí prstem k akci (akcelerátor dotykového ovládání)
- Obnovení dat (akcelerátor dotykového ovládání)
- Klávesové zkratky (akcelerátor klávesnice)
- Přístupové klávesy (akcelerátor klávesnice)
- Tlačítka pro najetí myši a pera (zrychlovač ukazatele)
Poznámka:
Uživatelé by měli mít přístup ke všem příkazům z libovolného typu zařízení. Například pokud jsou příkazy vaší aplikace dostupné pouze prostřednictvím tlačítek, která se objeví při přejetí ukazatelem myši, uživatelé dotykových zařízení k nim nebudou mít přístup. Pro zajištění přístupu ke všem příkazům použijte alespoň kontextové menu.
Příklad: Datový model PodcastObject
Abychom si ukázali naše přesvědčivá doporučení, tento článek vytvoří seznam podcastů pro aplikaci pro podcasty. Ukázkový kód demonstruje, jak uživateli umožnit označit konkrétní podcast ze seznamu jako oblíbený.
Tady je definice objektu podcastu, se kterým budeme pracovat:
public class PodcastObject : INotifyPropertyChanged
{
// The title of the podcast
public String Title { get; set; }
// The podcast's description
public String Description { get; set; }
// Describes if the user has set this podcast as a favorite
public bool IsFavorite
{
get
{
return _isFavorite;
}
set
{
_isFavorite = value;
OnPropertyChanged("IsFavorite");
}
}
private bool _isFavorite = false;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(String property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
Všimněte si, že PodcastObject implementuje INotifyPropertyChanged, aby reagoval na změny vlastností, když uživatel přepne vlastnost IsFavorite.
Definování příkazů pomocí rozhraní ICommand
Rozhraní ICommand vám pomůže definovat příkaz, který je k dispozici pro více typů vstupu. Například místo psaní stejného kódu pro příkaz delete ve dvou různých obslužných rutinách událostí, jeden pro, když uživatel stiskne klávesu Delete a druhý pro, když uživatel klikne pravým tlačítkem myši na Delete v místní nabídce, můžete logiku odstranění implementovat jednou, jako ICommand, a pak ji zpřístupnit různým typům vstupu.
Musíme definovat ICommand, který představuje akci Oblíbené. K označení podcastu jako oblíbeného použijeme metodu příkazu Execute. Konkrétní podcast bude poskytnut metodě execute prostřednictvím parametru příkazu, který může být vázán pomocí vlastnosti CommandParameter.
public class FavoriteCommand: ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
// Perform the logic to "favorite" an item.
(parameter as PodcastObject).IsFavorite = true;
}
}
Pokud chcete použít stejný příkaz s více kolekcemi a prvky, můžete tento příkaz uložit jako prostředek na stránce nebo v aplikaci.
<Application.Resources>
<local:FavoriteCommand x:Key="favoriteCommand" />
</Application.Resources>
Příkaz spustíte voláním metody Execute .
// Favorite the item using the defined command
var favoriteCommand = Application.Current.Resources["favoriteCommand"] as ICommand;
favoriteCommand.Execute(PodcastObject);
Vytvoření UserControl pro reakci na různé vstupy
Pokud máte seznam položek a každá z těchto položek by měla reagovat na více vstupů, můžete zjednodušit kód definováním UserControl pro položku a jeho použitím k definování místní nabídky položek a obslužných rutin událostí.
Vytvoření UserControl ve prostředí Visual Studio:
- V Průzkumníku řešení klikněte pravým tlačítkem myši na projekt. Zobrazí se místní nabídka.
- Vyberte Přidat > novou položku...
Zobrazí se dialogové okno Přidat novou položku . - V seznamu položek vyberte UserControl. Pojmenujte ho a klikněte na Přidat. Visual Studio pro vás vygeneruje šablonu UserControl.
V našem příkladu podcastu se každý podcast zobrazí v seznamu, který nabídne různé způsoby, jak podcast 'označit jako oblíbený'. Uživatel bude moct označit podcast jako "oblíbený" provedením následujících akcí:
- Vyvolejte místní nabídku
- Provádění klávesových zkratek
- Zobrazení tlačítka přechodu myší
- Gesto potáhnutí prstem
Pro zapouzdření těchto chování a použití FavoriteCommand vytvoříme nový UserControl s názvem PodcastUserControl, který bude představovat podcast v seznamu.
PodcastUserControl zobrazí pole PodcastObject jako TextBlocks a reaguje na různé interakce uživatelů. V tomto článku budeme odkazovat na PodcastUserControl a rozšiřovat ho.
PodcastUserControl.xaml
<UserControl
x:Class="ContextCommanding.PodcastUserControl"
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"
mc:Ignorable="d"
IsTabStop="True" UseSystemFocusVisuals="True"
>
<Grid Margin="12,0,12,0">
<StackPanel>
<TextBlock Text="{x:Bind PodcastObject.Title, Mode=OneWay}" Style="{StaticResource TitleTextBlockStyle}" />
<TextBlock Text="{x:Bind PodcastObject.Description, Mode=OneWay}" Style="{StaticResource SubtitleTextBlockStyle}" />
<TextBlock Text="{x:Bind PodcastObject.IsFavorite, Mode=OneWay}" Style="{StaticResource SubtitleTextBlockStyle}"/>
</StackPanel>
</Grid>
</UserControl>
PodcastUserControl.xaml.cs
public sealed partial class PodcastUserControl : UserControl
{
public static readonly DependencyProperty PodcastObjectProperty =
DependencyProperty.Register(
"PodcastObject",
typeof(PodcastObject),
typeof(PodcastUserControl),
new PropertyMetadata(null));
public PodcastObject PodcastObject
{
get { return (PodcastObject)GetValue(PodcastObjectProperty); }
set { SetValue(PodcastObjectProperty, value); }
}
public PodcastUserControl()
{
this.InitializeComponent();
// TODO: We will add event handlers here.
}
}
Všimněte si, že PodcastUserControl udržuje odkaz na PodcastObject jako DependencyProperty. To nám umožňuje vytvořit vazbu PodcastObjects na PodcastUserControl.
Po vygenerování některých objektů PodcastObjects můžete vytvořit seznam podcastů vytvořením vazby PodcastObjects k objektu ListView. PodcastUserControl objekty popisují vizualizaci PodcastObjects, a proto jsou nastaveny pomocí ListView ItemTemplate.
MainPage.xaml
<ListView x:Name="ListOfPodcasts"
ItemsSource="{x:Bind podcasts}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:PodcastObject">
<local:PodcastUserControl PodcastObject="{x:Bind Mode=OneWay}" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<!-- The PodcastUserControl will entirely fill the ListView item and handle tabbing within itself. -->
<Style TargetType="ListViewItem" BasedOn="{StaticResource ListViewItemRevealStyle}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="0"/>
<Setter Property="IsTabStop" Value="False"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Vytváření kontextových nabídek
Místní nabídky zobrazují seznam příkazů nebo možností, když si je uživatel vyžádá. Místní nabídky poskytují kontextové příkazy související s připojeným prvkem a jsou obvykle vyhrazeny pro sekundární akce specifické pro danou položku.
Uživatel může vyvolat místní nabídky pomocí těchto kontextových akcí:
| Vstup | Kontextová akce |
|---|---|
| Mouse | Kliknutí pravým tlačítkem myši |
| Keyboard | Shift+F10, tlačítko nabídky |
| Dotykové ovládání | Dlouhé stisknutí položky |
| Pero | Stiskněte tlačítko pera, dlouze stiskněte položku |
| Herní ovladač | Tlačítko nabídky |
Vzhledem k tomu, že uživatel může otevřít místní nabídku bez ohledu na typ vstupu, měla by místní nabídka obsahovat všechny kontextové příkazy dostupné pro položku seznamu.
ContextFlyout
Vlastnost ContextFlyout, definovaná třídou UIElement, usnadňuje vytvoření místní nabídky, která funguje se všemi typy vstupu. Poskytnete kontextovou nabídku pomocí MenuFlyout nebo CommandBarFlyout, a když uživatel provede "kontextovou akci" definovanou výše, zobrazí se MenuFlyout nebo CommandBarFlyout odpovídající dané položce.
Viz nabídky a kontextové nabídky, kde najdete nápovědu k identifikaci scénářů menu a kontextových nabídek a pokyny, kdy používat panelové menu vs. panel na panelu příkazů.
V tomto příkladu použijeme MenuFlyout a začneme přidáním ContextFlyout do PodcastUserControl. MenuFlyout zadaný jako ContextFlyout obsahuje jednu položku k označení podcastu jako oblíbeného. Všimněte si, že tento MenuFlyoutItem používá oblíbený příkaz definovaný výše, s parametrem příkazu, který je vázaný na objekt Podcast.
PodcastUserControl.xaml
<UserControl>
<UserControl.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem Text="Favorite" Command="{StaticResource favoriteCommand}" CommandParameter="{x:Bind PodcastObject, Mode=OneWay}" />
</MenuFlyout>
</UserControl.ContextFlyout>
<Grid Margin="12,0,12,0">
<!-- ... -->
</Grid>
</UserControl>
Všimněte si, že k reakci na kontextové akce můžete použít také událost ContextRequested . Událost ContextRequested se neaktivuje, pokud byl zadán ContextFlyout.
Vytváření vstupních akcelerátorů
I když každá položka v kolekci by měla mít místní nabídku obsahující všechny kontextové příkazy, můžete uživatelům umožnit rychle provádět menší sadu často prováděných příkazů. Poštovní aplikace může mít například sekundární příkazy, jako je Odpovědět, Archivovat, Přesunout do složky, Nastavit příznak a Odstranit, které se zobrazí v místní nabídce, ale nejběžnější příkazy jsou Odstranit a Označit příznakem. Jakmile zjistíte, které příkazy jsou nejběžnější, můžete pomocí akcelerátorů založených na vstupu usnadnit provádění těchto příkazů uživateli.
V aplikaci podcastu je často používaným příkazem možnost "Oblíbené".
Klávesové akcelerátory
Klávesové zkratky a přímé zpracování kláves
V závislosti na typu obsahu můžete identifikovat určité kombinace kláves, které by měly provést akci. V e-mailové aplikaci se například klíč DEL může použít k odstranění vybraného e-mailu. V aplikaci podcastu můžou klávesové zkratky Ctrl+S nebo F znamenat, že pro pozdější použití můžete podcast přidat mezi oblíbené. I když některé příkazy mají běžné, dobře známé klávesové zkratky, jako je DEL k odstranění, jiné příkazy mají klávesové zkratky specifické pro aplikaci nebo doménu. Pokud je to možné, používejte známé klávesové zkratky nebo zvažte poskytnutí upozorňujícího textu v popisu, abyste uživatele naučili o klávesové zkratce.
Aplikace může reagovat, když uživatel stiskne klávesu pomocí události KeyDown . Uživatelé obecně očekávají, že aplikace odpoví při prvním stisknutí klávesy dolů, a nečekají na uvolnění klíče.
Tento příklad ukazuje, jak přidat obslužnou rutinu KeyDown do 'PodcastUserControl', aby byl podcast označen jako oblíbený při stisknutí Ctrl+S nebo F. Používá se stejný příkaz jako předtím.
PodcastUserControl.xaml.cs
// Respond to the F and Ctrl+S keys to favorite the focused item.
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
var isCtrlPressed = (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down || (ctrlState & CoreVirtualKeyStates.Locked) == CoreVirtualKeyStates.Locked;
if (e.Key == Windows.System.VirtualKey.F || (e.Key == Windows.System.VirtualKey.S && isCtrlPressed))
{
// Favorite the item using the defined command
var favoriteCommand = Application.Current.Resources["favoriteCommand"] as ICommand;
favoriteCommand.Execute(PodcastObject);
}
}
Akcelerátory myši
Uživatelé jsou obeznámeni s místními nabídkami po kliknutí pravým tlačítkem myši, ale možná budete chtít uživatelům umožnit provádět běžné příkazy jenom jedním kliknutím myši. Pokud chcete tuto funkci povolit, můžete na plátně položky kolekce zahrnout vyhrazená tlačítka. Pokud chcete uživatelům umožnit rychle pracovat pomocí myši a minimalizovat vizuální nepotřebné prvky, můžete tato tlačítka zobrazit jenom v případě, že má uživatel ukazatel v určité položce seznamu.
V tomto příkladu je příkaz Oblíbené reprezentován tlačítkem definovaným přímo v PodcastUserControl. Všimněte si, že tlačítko v tomto příkladu používá stejný příkaz FavoriteCommand jako předtím. Pokud chcete přepnout viditelnost tohoto tlačítka, můžete pomocí visualStateManager přepínat mezi vizuálními stavy, když ukazatel vstoupí do ovládacího prvku a ukončí ho.
PodcastUserControl.xaml
<UserControl>
<UserControl.ContextFlyout>
<!-- ... -->
</UserControl.ContextFlyout>
<Grid Margin="12,0,12,0">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="HoveringStates">
<VisualState x:Name="HoverButtonsShown">
<VisualState.Setters>
<Setter Target="hoverArea.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="HoverButtonsHidden" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="{x:Bind PodcastObject.Title, Mode=OneWay}" Style="{StaticResource TitleTextBlockStyle}" />
<TextBlock Text="{x:Bind PodcastObject.Description, Mode=OneWay}" Style="{StaticResource SubtitleTextBlockStyle}" />
<TextBlock Text="{x:Bind PodcastObject.IsFavorite, Mode=OneWay}" Style="{StaticResource SubtitleTextBlockStyle}"/>
</StackPanel>
<Grid Grid.Column="1" x:Name="hoverArea" Visibility="Collapsed" VerticalAlignment="Stretch">
<AppBarButton Icon="OutlineStar" Label="Favorite" Command="{StaticResource favoriteCommand}" CommandParameter="{x:Bind PodcastObject, Mode=OneWay}" IsTabStop="False" VerticalAlignment="Stretch" />
</Grid>
</Grid>
</UserControl>
Tlačítka najetí myší by se měla zobrazit a zmizet, když myš přejde a ukončí položku. K reakci na události myši můžete použít události PointerEntered a PointerExited na PodcastUserControl.
PodcastUserControl.xaml.cs
protected override void OnPointerEntered(PointerRoutedEventArgs e)
{
base.OnPointerEntered(e);
// Only show hover buttons when the user is using mouse or pen.
if (e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse || e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Pen)
{
VisualStateManager.GoToState(this, "HoverButtonsShown", true);
}
}
protected override void OnPointerExited(PointerRoutedEventArgs e)
{
base.OnPointerExited(e);
VisualStateManager.GoToState(this, "HoverButtonsHidden", true);
}
Tlačítka zobrazená ve stavu přechodu myší budou přístupná pouze prostřednictvím vstupního typu ukazatele. Vzhledem k tomu, že jsou tato tlačítka omezena na vstup ukazatele, můžete se rozhodnout minimalizovat nebo odebrat odsazení kolem ikony tlačítka, abyste optimalizovali vstup ukazatele. Pokud se tak rozhodnete, ujistěte se, že je stopa tlačítka minimálně 20 × 20 pixelů, aby zůstala použitelná pomocí pera a myši.
Dotykové akcelerátory
Swipe
Příkaz potáhnutí prstem je akcelerátor dotykového ovládání, který umožňuje uživatelům na dotykových zařízeních provádět běžné sekundární akce pomocí dotykového ovládání. Potáhnutí prstem umožňuje uživatelům rychle a přirozeně pracovat s obsahem pomocí běžných akcí, jako je potažení prstem pro odstranění nebo vyvolání funkce potažením. Podívejte se na článek o příkazu potáhnutí prstem a zjistěte více.
K integraci potáhnutí prstem do kolekce potřebujete dvě komponenty: SwipeItems, které hostují příkazy; a SwipeControl, který zabalí položku a umožňuje interakci s potáhnutím prstem.
SwipeItems mohou být definovány jako zdroj v PodcastUserControl. V tomto příkladu kolekce SwipeItems obsahuje příkaz k označení položky jako oblíbené.
<UserControl.Resources>
<SymbolIconSource x:Key="FavoriteIcon" Symbol="Favorite"/>
<SwipeItems x:Key="RevealOtherCommands" Mode="Reveal">
<SwipeItem IconSource="{StaticResource FavoriteIcon}" Text="Favorite" Background="Yellow" Invoked="SwipeItem_Invoked"/>
</SwipeItems>
</UserControl.Resources>
SwipeControl zabalí položku a umožní uživateli pracovat s ní pomocí gesta potáhnutí prstem. Všimněte si, že SwipeControl obsahuje odkaz na SwipeItems jako své pravé položky (RightItems). Položka Oblíbené se zobrazí, když uživatel potáhne prstem zprava doleva.
<SwipeControl x:Name="swipeContainer" RightItems="{StaticResource RevealOtherCommands}">
<!-- The visual state groups moved from the Grid to the SwipeControl, since the SwipeControl wraps the Grid. -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="HoveringStates">
<VisualState x:Name="HoverButtonsShown">
<VisualState.Setters>
<Setter Target="hoverArea.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="HoverButtonsHidden" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="12,0,12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="{x:Bind PodcastObject.Title, Mode=OneWay}" Style="{StaticResource TitleTextBlockStyle}" />
<TextBlock Text="{x:Bind PodcastObject.Description, Mode=OneWay}" Style="{StaticResource SubtitleTextBlockStyle}" />
<TextBlock Text="{x:Bind PodcastObject.IsFavorite, Mode=OneWay}" Style="{StaticResource SubtitleTextBlockStyle}"/>
</StackPanel>
<Grid Grid.Column="1" x:Name="hoverArea" Visibility="Collapsed" VerticalAlignment="Stretch">
<AppBarButton Icon="OutlineStar" Command="{StaticResource favoriteCommand}" CommandParameter="{x:Bind PodcastObject, Mode=OneWay}" IsTabStop="False" LabelPosition="Collapsed" VerticalAlignment="Stretch" />
</Grid>
</Grid>
</SwipeControl>
Když uživatel potáhne prstem pro vyvolání příkazu Oblíbené, je zavolána metoda Invoked.
private void SwipeItem_Invoked(SwipeItem sender, SwipeItemInvokedEventArgs args)
{
// Favorite the item using the defined command
var favoriteCommand = Application.Current.Resources["favoriteCommand"] as ICommand;
favoriteCommand.Execute(PodcastObject);
}
Táhněte pro obnovení
Funkce Pull to Refresh umožňuje uživateli stáhnout kolekci dat pomocí dotykového ovládání, aby načetl další data. Podívejte se do článku pull to refresh, kde se dozvíte více.
Akcelerátory pera
Typ zadávání pera poskytuje přesnost vstupu ukazatele. Uživatelé můžou provádět běžné akce, jako je otevření kontextových nabídek pomocí akcelerátorů založených na peru. Pokud chcete otevřít místní nabídku, můžou uživatelé klepnout na obrazovku stisknutím tlačítka sudu nebo dlouho stisknout obsah. Uživatelé můžou také pomocí pera najet nad obsahem, aby získali hlubší přehled o uživatelském rozhraní, jako je zobrazení bublinové nápovědy, nebo k odhalení sekundárních akcí při najetí, podobně jako myš.
Pokud chcete aplikaci optimalizovat pro zadávání perem, přečtěte si článek interakce pera a pera .
Recommendations
- Ujistěte se, že uživatelé mají přístup ke všem příkazům ze všech typů zařízení s Windows.
- Zahrnout kontextovou nabídku, která poskytuje přístup ke všem příkazům dostupným pro položku kolekce.
- Zadejte vstupní akcelerátory pro často používané příkazy.
- K implementaci příkazů použijte rozhraní ICommand .
Související témata
Windows developer