Perintah kontekstual untuk koleksi dan daftar

Banyak aplikasi berisi kumpulan konten dalam bentuk daftar, kisi, dan pohon yang dapat dimanipulasi pengguna. Misalnya, pengguna mungkin dapat menghapus, mengganti nama, menandai, atau menyegarkan item. Artikel ini menunjukkan kepada Anda cara menggunakan perintah kontekstual untuk mengimplementasikan tindakan semacam ini dengan cara yang memberikan pengalaman terbaik untuk semua jenis input.

API Penting: Antarmuka ICommand, properti UIElement.ContextFlyout, antarmuka INotifyPropertyChanged

Use a variety of inputs to perform the Favorite command

Membuat perintah untuk semua jenis input

Karena pengguna dapat berinteraksi dengan aplikasi Windows menggunakan berbagai perangkat dan input, aplikasi Anda harus mengekspos perintah melalui menu konteks input-agnostik dan akselerator khusus input. Termasuk keduanya memungkinkan pengguna dengan cepat memanggil perintah pada konten, terlepas dari input atau jenis perangkat.

Tabel ini memperlihatkan beberapa perintah koleksi umum dan cara untuk mengekspos perintah tersebut.

Perintah Input-agnostik Akselerator mouse Akselerator keyboard Akselerator sentuh
Hapus item Menu Konteks Tombol Arahkan mouse ke arah yang lebih tinggi Kunci DEL Gesek untuk menghapus
Bendera item Menu Konteks Tombol Arahkan mouse ke arah yang lebih tinggi Ctrl+Shift+G Gesek ke bendera
Memuat ulang data Menu Konteks T/A Kunci F5 Tarik untuk menyegarkan
Favoritkan item Menu Konteks Tombol Arahkan mouse ke arah yang lebih tinggi F, Ctrl+S Geser ke favorit
  • Secara umum, Anda harus membuat semua perintah untuk item tersedia di menu konteks item. Menu konteks dapat diakses oleh pengguna terlepas dari jenis input, dan harus berisi semua perintah kontekstual yang dapat dilakukan pengguna.

  • Untuk perintah yang sering diakses, pertimbangkan untuk menggunakan akselerator input. Akselerator input memungkinkan pengguna melakukan tindakan dengan cepat, berdasarkan perangkat input mereka. Akselerator input meliputi:

    • Gesek ke tindakan (akselerator sentuh)
    • Tarik untuk menyegarkan data (akselerator sentuh)
    • Pintasan keyboard (akselerator keyboard)
    • Tombol akses (akselerator keyboard)
    • Tombol Mouse & Pena melayang (akselerator penunjuk)

Catatan

Pengguna harus dapat mengakses semua perintah dari semua jenis perangkat. Misalnya, jika perintah aplikasi Anda hanya diekspos melalui akselerator penunjuk tombol hover, pengguna sentuh tidak akan dapat mengaksesnya. Minimal, gunakan menu konteks untuk menyediakan akses ke semua perintah.

Contoh: Model data PodcastObject

Untuk menunjukkan rekomendasi perintah kami, artikel ini membuat daftar podcast untuk aplikasi podcast. Contoh kode menunjukkan cara mengaktifkan pengguna untuk "favorit" podcast tertentu dari daftar.

Berikut adalah definisi untuk objek podcast yang akan kita kerjakan:

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));
    }
}

Perhatikan bahwa PodcastObject mengimplementasikan INotifyPropertyChanged untuk merespons perubahan properti saat pengguna mengaktifkan properti IsFavorite.

Menentukan perintah dengan antarmuka ICommand

Antarmuka ICommand membantu Anda menentukan perintah yang tersedia untuk beberapa jenis input. Misalnya, alih-alih menulis kode yang sama untuk perintah hapus di dua penanganan aktivitas yang berbeda, satu untuk ketika pengguna menekan tombol Hapus dan satu untuk ketika pengguna mengklik kanan "Hapus" di menu konteks, Anda dapat mengimplementasikan logika penghapusan Anda sekali, sebagai ICommand, dan kemudian membuatnya tersedia untuk jenis input yang berbeda.

Kita perlu menentukan ICommand yang mewakili tindakan "Favorit". Kita akan menggunakan metode Jalankan perintah untuk memfavoritkan podcast. Podcast tertentu akan diberikan ke metode eksekusi melalui parameter perintah, yang dapat diikat menggunakan properti 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;
    }
}

Untuk menggunakan perintah yang sama dengan beberapa koleksi dan elemen, Anda dapat menyimpan perintah sebagai sumber daya di halaman atau di aplikasi.

<Application.Resources>
    <local:FavoriteCommand x:Key="favoriteCommand" />
</Application.Resources>

Untuk menjalankan perintah, Anda memanggil metode Execute-nya.

// Favorite the item using the defined command
var favoriteCommand = Application.Current.Resources["favoriteCommand"] as ICommand;
favoriteCommand.Execute(PodcastObject);

Membuat UserControl untuk merespons berbagai input

Ketika Anda memiliki daftar item dan masing-masing item tersebut harus merespons beberapa input, Anda dapat menyederhanakan kode Anda dengan menentukan UserControl untuk item dan menggunakannya untuk menentukan menu konteks item dan penanganan peristiwa Anda.

Untuk membuat UserControl di Visual Studio:

  1. Di Penjelajah Solusi, klik kanan proyek. Menu konteks muncul.
  2. Pilih Tambahkan > Item Baru...
    Dialog Tambahkan Item Baru muncul.
  3. Pilih UserControl dari daftar item. Beri nama yang Anda inginkan dan klik Tambahkan. Visual Studio akan menghasilkan UserControl stub untuk Anda.

Dalam contoh podcast kami, setiap podcast akan ditampilkan dalam daftar, yang akan mengekspos berbagai cara untuk "Favorit" podcast. Pengguna akan dapat melakukan tindakan berikut ke "Favorit" podcast:

  • Memanggil menu konteks
  • Melakukan pintasan keyboard
  • Perlihatkan tombol hover
  • Melakukan gerakan gesek

Untuk merangkum perilaku ini dan menggunakan FavoriteCommand, mari kita buat UserControl baru bernama "PodcastUserControl" untuk mewakili podcast dalam daftar.

PodcastUserControl menampilkan bidang PodcastObject sebagai TextBlocks, dan merespons berbagai interaksi pengguna. Kami akan mereferensikan dan memperluas PodcastUserControl di seluruh artikel ini.

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

Perhatikan bahwa PodcastUserControl mempertahankan referensi ke PodcastObject sebagai DependencyProperty. Ini memungkinkan kita untuk mengikat PodcastObjects ke PodcastUserControl.

Setelah membuat beberapa PodcastObjects, Anda dapat membuat daftar podcast dengan mengikat PodcastObjects ke ListView. Objek PodcastUserControl menjelaskan visualisasi PodcastObjects, dan karenanya diatur menggunakan ItemTemplate ListView.

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>

Membuat menu konteks

Menu konteks menampilkan daftar perintah atau opsi saat pengguna memintanya. Menu konteks menyediakan perintah kontekstual yang terkait dengan elemen terlampirnya, dan umumnya dicadangkan untuk tindakan sekunder khusus untuk item tersebut.

Show a context menu on the item

Pengguna dapat memanggil menu konteks menggunakan "tindakan konteks" ini:

Input Tindakan konteks
Mouse Klik kanan
Keyboard Shift+F10, tombol Menu
Sentuh Tekan lama pada item
Pena Tekan tombol barel, tekan panjang item
Gamepad Tombol Menu

Karena pengguna dapat membuka menu konteks terlepas dari jenis input, menu konteks Anda harus berisi semua perintah kontekstual yang tersedia untuk item daftar.

ContextFlyout

Properti ContextFlyout, yang ditentukan oleh kelas UIElement, memudahkan untuk membuat menu konteks yang berfungsi dengan semua jenis input. Anda menyediakan flyout yang mewakili menu konteks Anda menggunakan MenuFlyout atau CommandBarFlyout, dan ketika pengguna melakukan "tindakan konteks" seperti yang didefinisikan di atas, MenuFlyout atau CommandBarFlyout yang sesuai dengan item akan ditampilkan.

Lihat menu dan menu konteks untuk membantu mengidentifikasi menu vs. skenario menu konteks dan panduan tentang kapan menggunakan flyout menu vs. flyout bilah perintah.

Untuk contoh ini, kita akan menggunakan MenuFlyout dan akan dimulai dengan menambahkan ContextFlyout ke PodcastUserControl. MenuFlyout yang ditentukan sebagai ContextFlyout berisi satu item untuk memfavoritkan podcast. Perhatikan bahwa MenuFlyoutItem ini menggunakan favoriteCommand yang ditentukan di atas, dengan CommandParameter terikat ke PodcastObject.

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>

Perhatikan bahwa Anda juga dapat menggunakan peristiwa ContextRequested untuk merespons tindakan konteks. Peristiwa ContextRequested tidak akan diaktifkan jika ContextFlyout telah ditentukan.

Membuat akselerator input

Meskipun setiap item dalam koleksi harus memiliki menu konteks yang berisi semua perintah kontekstual, Anda mungkin ingin memungkinkan pengguna untuk dengan cepat melakukan serangkaian perintah yang sering dilakukan. Misalnya, aplikasi surat mungkin memiliki perintah sekunder seperti Balas, Arsip, Pindahkan ke Folder, Atur Bendera, dan Hapus yang muncul di menu konteks, tetapi perintah yang paling umum adalah Hapus dan Bendera. Setelah mengidentifikasi perintah mana yang paling umum, Anda dapat menggunakan akselerator berbasis input untuk membuat perintah ini lebih mudah dilakukan pengguna.

Di aplikasi podcast, perintah yang sering dilakukan adalah perintah "Favorit".

Akselerator keyboard

Pintasan dan penanganan kunci langsung

Press Ctrl and F to perform an action

Bergantung pada jenis konten, Anda dapat mengidentifikasi kombinasi kunci tertentu yang harus melakukan tindakan. Di aplikasi email, misalnya, kunci DEL dapat digunakan untuk menghapus email yang dipilih. Dalam aplikasi podcast, kunci Ctrl+S atau F dapat memfavoritkan podcast untuk nanti. Meskipun beberapa perintah memiliki pintasan keyboard umum dan terkenal seperti DEL untuk dihapus, perintah lain memiliki pintasan khusus aplikasi atau domain. Gunakan pintasan terkenal jika memungkinkan, atau pertimbangkan untuk memberikan teks pengingat dalam tipsalat untuk mengajari pengguna tentang perintah pintasan.

Aplikasi Anda dapat merespons saat pengguna menekan tombol menggunakan peristiwa KeyDown . Secara umum, pengguna mengharapkan bahwa aplikasi akan merespons ketika mereka pertama kali menekan tombol ke bawah, daripada menunggu sampai mereka merilis kunci.

Contoh ini menjelaskan cara menambahkan handler KeyDown ke PodcastUserControl ke podcast favorit saat pengguna menekan Ctrl+S atau F. Ini menggunakan perintah yang sama seperti sebelumnya.

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);
    }
}

Akselerator mouse

Hover the mouse over an item to reveal a button

Pengguna terbiasa dengan menu konteks klik kanan, tetapi Anda mungkin ingin memberdayakan pengguna untuk melakukan perintah umum hanya menggunakan satu klik mouse. Untuk mengaktifkan pengalaman ini, Anda dapat menyertakan tombol khusus di kanvas item koleksi Anda. Untuk memberdayakan pengguna untuk bertindak cepat menggunakan mouse, dan untuk meminimalkan kekacauan visual, Anda dapat memilih untuk hanya mengungkapkan tombol-tombol ini ketika pengguna memiliki pointer mereka dalam item daftar tertentu.

Dalam contoh ini, perintah Favorit diwakili oleh tombol yang ditentukan langsung di PodcastUserControl. Perhatikan bahwa tombol dalam contoh ini menggunakan perintah yang sama, FavoriteCommand, seperti sebelumnya. Untuk mengalihkan visibilitas tombol ini, Anda dapat menggunakan VisualStateManager untuk beralih antar status visual saat penunjuk memasuki dan keluar dari kontrol.

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>

Tombol arahkan kursor akan muncul dan menghilang saat mouse masuk dan keluar dari item. Untuk menanggapi peristiwa mouse, Anda dapat menggunakan peristiwa PointerEntered dan PointerExited di 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);
}

Tombol yang ditampilkan dalam status hover hanya akan dapat diakses melalui jenis input penunjuk. Karena tombol ini terbatas pada input pointer, Anda dapat memilih untuk meminimalkan atau menghapus padding di sekitar ikon tombol untuk mengoptimalkan input pointer. Jika Anda memilih untuk melakukannya, pastikan bahwa jejak tombol setidaknya 20x20px untuk tetap dapat digunakan dengan pena dan mouse.

Akselerator sentuh

Babatan

Swipe an item to reveal the command

Perintah gesek adalah akselerator sentuh yang memungkinkan pengguna pada perangkat sentuh melakukan tindakan sekunder umum menggunakan sentuhan. Geser memberdayakan pengguna untuk berinteraksi dengan konten dengan cepat dan alami, menggunakan tindakan umum seperti Swipe-to-Delete atau Swipe-to-Invoke. Lihat artikel perintah gesek untuk mempelajari selengkapnya.

Untuk mengintegrasikan gesek ke dalam koleksi Anda, Anda memerlukan dua komponen: SwipeItems, yang menghosting perintah; dan SwipeControl, yang membungkus item dan memungkinkan interaksi gesek.

SwipeItems dapat didefinisikan sebagai Sumber Daya di PodcastUserControl. Dalam contoh ini, SwipeItems berisi perintah ke Favoritkan item.

<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 membungkus item dan memungkinkan pengguna untuk berinteraksi dengannya menggunakan gerakan gesek. Perhatikan bahwa SwipeControl berisi referensi ke SwipeItems sebagai RightItems-nya. Item Favorit akan ditampilkan saat pengguna menggesek dari kanan ke kiri.

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

Ketika pengguna menggesek untuk memanggil perintah Favorit, metode Yang dipanggil dipanggil dipanggil.

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);
}

Tarik untuk menyegarkan

Tarik untuk menyegarkan memungkinkan pengguna menarik ke bawah pada kumpulan data menggunakan sentuhan untuk mengambil lebih banyak data. Lihat artikel tarik untuk me-refresh untuk mempelajari selengkapnya.

Akselerator pena

Jenis input pena menyediakan presisi input pointer. Pengguna dapat melakukan tindakan umum seperti membuka menu konteks menggunakan akselerator berbasis pena. Untuk membuka menu konteks, pengguna dapat mengetuk layar dengan tombol laras ditekan, atau menekan lama konten. Pengguna juga dapat menggunakan pena untuk mengarahkan kursor ke konten untuk mendapatkan pemahaman yang lebih mendalam tentang UI seperti menampilkan tipsalat, atau untuk mengungkapkan tindakan hover sekunder, mirip dengan mouse.

Untuk mengoptimalkan aplikasi Anda untuk input pena, lihat artikel interaksi pena dan stylus.

Rekomendasi

  • Pastikan pengguna dapat mengakses semua perintah dari semua jenis perangkat Windows.
  • Sertakan menu konteks yang menyediakan akses ke semua perintah yang tersedia untuk item koleksi.
  • Berikan akselerator input untuk perintah yang sering digunakan.
  • Gunakan antarmuka ICommand untuk mengimplementasikan perintah.