Bagikan melalui


Gambaran Umum Perintah

Perintah adalah mekanisme input di Windows Presentation Foundation (WPF) yang menyediakan penanganan input pada tingkat yang lebih semantik daripada input perangkat. Contoh perintah adalah fungsi Salin, Potong, dan Tempel yang ditemukan di banyak aplikasi perangkat lunak.

Gambaran umum ini mendefinisikan perintah apa yang ada di WPF, kelas mana yang merupakan bagian dari model perintah, dan cara menggunakan dan membuat perintah di aplikasi Anda.

Topik ini berisi bagian berikut:

Apa Itu Perintah

Perintah memiliki beberapa tujuan. Tujuan pertama adalah untuk memisahkan semantik dan objek yang memanggil perintah dari logika yang menjalankan perintah. Ini memungkinkan beberapa sumber yang berbeda untuk memanggil logika perintah yang sama, dan memungkinkan logika perintah disesuaikan untuk target yang berbeda. Misalnya, operasi pengeditan Salin, Potong, dan Tempel, yang ditemukan di banyak aplikasi, dapat dipanggil dengan menggunakan tindakan pengguna yang berbeda jika diimplementasikan dengan menggunakan perintah. Aplikasi mungkin memungkinkan pengguna untuk memotong objek atau teks yang dipilih dengan mengklik tombol, memilih item di menu, atau menggunakan kombinasi kunci, seperti CTRL+X. Dengan menggunakan perintah, Anda dapat mengikat setiap jenis tindakan pengguna ke logika yang sama.

Tujuan lain dari perintah adalah untuk menunjukkan apakah tindakan tersedia. Untuk melanjutkan contoh pemotongan objek atau teks, tindakan hanya masuk akal ketika sesuatu dipilih. Jika pengguna mencoba memotong objek atau teks tanpa memilih apa pun, tidak ada yang akan terjadi. Untuk menunjukkan hal ini kepada pengguna, banyak aplikasi menonaktifkan tombol dan item menu sehingga pengguna tahu apakah mungkin untuk melakukan tindakan. Perintah dapat menunjukkan apakah tindakan dimungkinkan dengan menerapkan CanExecute metode . Tombol dapat berlangganan pada CanExecuteChanged peristiwa dan dinonaktifkan jika CanExecute mengembalikan false atau diaktifkan jika CanExecute mengembalikan true.

Semantik perintah dapat konsisten di seluruh aplikasi dan kelas, tetapi logika tindakan khusus untuk objek tertentu yang dioperasikan. Kombinasi kunci CTRL+X memanggil perintah Potong di kelas teks, kelas gambar, dan browser Web, tetapi logika aktual untuk melakukan operasi Potong ditentukan oleh aplikasi yang melakukan pemotongan. RoutedCommand memungkinkan klien untuk mengimplementasikan logika. Objek teks dapat memotong teks terpilih ke clipboard, sementara objek gambar dapat memotong gambar yang dipilih. Ketika aplikasi menangani Executed peristiwa, aplikasi memiliki akses ke target perintah dan dapat mengambil tindakan yang sesuai tergantung pada jenis target.

Contoh Perintah Sederhana di WPF

Cara paling sederhana untuk menggunakan perintah di WPF adalah dengan menggunakan yang telah RoutedCommand ditentukan sebelumnya dari salah satu kelas pustaka perintah; gunakan kontrol yang memiliki dukungan asli untuk menangani perintah; dan menggunakan kontrol yang memiliki dukungan asli untuk memanggil perintah. Perintah Paste adalah salah satu perintah yang telah ditentukan sebelumnya di ApplicationCommands kelas . Kontrol TextBox memiliki logika bawaan untuk menangani perintah Paste. Kelas MenuItem menyediakan dukungan bawaan untuk memanggil perintah.

Contoh berikut menunjukkan cara menyiapkan MenuItem sehingga ketika diklik, perintah Paste akan dipanggil pada TextBox, dengan asumsi TextBox memiliki fokus keyboard.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;
' Creating the UI objects
Dim mainStackPanel As New StackPanel()
Dim pasteTextBox As New TextBox()
Dim stackPanelMenu As New Menu()
Dim pasteMenuItem As New MenuItem()

' Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem)
mainStackPanel.Children.Add(stackPanelMenu)
mainStackPanel.Children.Add(pasteTextBox)

' Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste

Empat Konsep Utama dalam Perintah WPF

Model perintah yang dirutekan di WPF dapat dipecah menjadi empat konsep utama: perintah, sumber perintah, target perintah, dan pengikatan perintah:

  • Perintah adalah tindakan yang akan dijalankan.

  • Sumber perintah adalah objek yang memanggil perintah.

  • Target perintah adalah objek tempat perintah dijalankan.

  • Pengikatan perintah adalah objek yang memetakan logika perintah ke perintah.

Dalam contoh sebelumnya, Paste perintah adalah perintah, MenuItem adalah sumber perintah, TextBox adalah target perintah, dan pengikatan perintah disediakan oleh TextBox kontrol. Perlu dicatat bahwa tidak selalu terjadi bahwa CommandBinding disediakan oleh kontrol yang merupakan kelas target perintah. Cukup sering CommandBinding harus dibuat oleh pengembang aplikasi, atau CommandBinding mungkin dilampirkan ke elemen induk dari target perintah.

Perintah

Perintah di WPF dibuat dengan mengimplementasikan ICommand antarmuka. ICommand mengekspos dua metode, Execute, dan CanExecute, dan peristiwa, CanExecuteChanged. Execute melakukan tindakan yang terkait dengan perintah . CanExecute menentukan apakah perintah dapat dijalankan pada target perintah saat ini. CanExecuteChanged dimunculkan jika manajer perintah yang memusatkan operasi perintah mendeteksi perubahan sumber perintah yang mungkin membatalkan perintah yang telah dimunculkan tetapi belum dijalankan oleh pengikatan perintah. Implementasi ICommand WPF adalah kelas RoutedCommand dan merupakan fokus dari tinjauan ini.

Sumber utama input dalam WPF adalah mouse, keyboard, tinta, dan perintah yang dirutekan. Semakin banyak input berorientasi perangkat menggunakan RoutedEvent untuk memberi tahu objek di halaman aplikasi bahwa peristiwa input telah terjadi. A RoutedCommand tidak berbeda. Metode Execute dan CanExecute dari sebuah RoutedCommand tidak berisi logika aplikasi untuk perintah, sebaliknya, mereka memicu peristiwa rute yang menyebar dan membesar melalui pohon elemen sampai mereka menemukan objek dengan CommandBinding. CommandBinding berisi handler untuk peristiwa ini dan merupakan handler yang melakukan perintah. Untuk informasi selengkapnya tentang perutean peristiwa di WPF, lihat Gambaran Umum Peristiwa Yang Dirutekan.

Metode Execute pada RoutedCommand memicu PreviewExecuted dan Executed event pada sasaran perintah. Metode CanExecute pada RoutedCommand memicu peristiwa CanExecute dan PreviewCanExecute pada sasaran perintah. Peristiwa ini mengalir dan muncul melalui pohon elemen hingga mereka menemukan objek yang memiliki CommandBinding untuk perintah tertentu.

WPF menyediakan serangkaian perintah rute umum yang tersebar di beberapa kelas: MediaCommands, , ApplicationCommands, NavigationCommandsComponentCommands, dan EditingCommands. Kelas-kelas ini hanya terdiri dari RoutedCommand objek dan bukan logika implementasi perintah. Logika implementasi adalah tanggung jawab objek tempat perintah dijalankan.

Sumber Perintah

Sumber perintah adalah objek yang memanggil perintah. Contoh sumber perintah adalah MenuItem, , Buttondan KeyGesture.

Sumber perintah di WPF umumnya mengimplementasikan antarmuka ICommandSource.

ICommandSource mengekspos tiga properti: Command, CommandTarget, dan CommandParameter:

Kelas WPF yang mengimplementasikan ICommandSource adalah ButtonBase, MenuItem, Hyperlink, dan InputBinding. ButtonBase, MenuItem, dan Hyperlink memanggil perintah ketika diklik, dan InputBinding memanggil perintah ketika InputGesture yang terkait dilakukan.

Contoh berikut menunjukkan cara menggunakan MenuItem di ContextMenu sebagai sumber perintah untuk Properties perintah.

<StackPanel>
  <StackPanel.ContextMenu>
    <ContextMenu>
      <MenuItem Command="ApplicationCommands.Properties" />
    </ContextMenu>
  </StackPanel.ContextMenu>
</StackPanel>
StackPanel cmdSourcePanel = new StackPanel();
ContextMenu cmdSourceContextMenu = new ContextMenu();
MenuItem cmdSourceMenuItem = new MenuItem();

// Add ContextMenu to the StackPanel.
cmdSourcePanel.ContextMenu = cmdSourceContextMenu;
cmdSourcePanel.ContextMenu.Items.Add(cmdSourceMenuItem);

// Associate Command with MenuItem.
cmdSourceMenuItem.Command = ApplicationCommands.Properties;
Dim cmdSourcePanel As New StackPanel()
Dim cmdSourceContextMenu As New ContextMenu()
Dim cmdSourceMenuItem As New MenuItem()

' Add ContextMenu to the StackPanel.
cmdSourcePanel.ContextMenu = cmdSourceContextMenu
cmdSourcePanel.ContextMenu.Items.Add(cmdSourceMenuItem)

' Associate Command with MenuItem.
cmdSourceMenuItem.Command = ApplicationCommands.Properties

Biasanya, sumber perintah akan mendengarkan peristiwa.CanExecuteChanged Kejadian ini menginformasikan sumber perintah bahwa kemampuan perintah untuk dijalankan pada target perintah saat ini mungkin telah berubah. Sumber perintah dapat membuat kueri status saat ini dari RoutedCommand dengan menggunakan metode CanExecute. Sumber perintah kemudian dapat menonaktifkan dirinya sendiri jika perintah tidak dapat dijalankan. Contohnya adalah MenuItem menjadi abu-abu ketika perintah tidak dapat dijalankan.

InputGesture dapat digunakan sebagai sumber perintah. Dua jenis gerakan input dalam WPF adalah KeyGesture dan MouseGesture. Anda dapat menganggap KeyGesture sebagai pintasan keyboard, seperti CTRL+C. KeyGesture terdiri dari sebuah Key dan satu set ModifierKeys. MouseGesture terdiri dari MouseAction serta set ModifierKeys opsional.

Agar sebuah InputGesture dapat bertindak sebagai sumber perintah, InputGesture harus dikaitkan dengan sebuah perintah. Ada beberapa cara untuk mencapai hal ini. Salah satu caranya adalah dengan menggunakan InputBinding.

Contoh berikut menunjukkan cara membuat KeyBinding antara KeyGesture dan RoutedCommand.

<Window.InputBindings>
  <KeyBinding Key="B"
              Modifiers="Control" 
              Command="ApplicationCommands.Open" />
</Window.InputBindings>
KeyGesture OpenKeyGesture = new KeyGesture(
    Key.B,
    ModifierKeys.Control);

KeyBinding OpenCmdKeybinding = new KeyBinding(
    ApplicationCommands.Open,
    OpenKeyGesture);

this.InputBindings.Add(OpenCmdKeybinding);
Dim OpenKeyGesture As New KeyGesture(Key.B, ModifierKeys.Control)

Dim OpenCmdKeybinding As New KeyBinding(ApplicationCommands.Open, OpenKeyGesture)

Me.InputBindings.Add(OpenCmdKeybinding)

Cara lain untuk mengaitkan InputGesture ke a RoutedCommand adalah dengan menambahkan InputGesture ke InputGestureCollection pada RoutedCommand.

Contoh berikut menunjukkan cara menambahkan KeyGesture ke InputGestureCollection dari RoutedCommand.

KeyGesture OpenCmdKeyGesture = new KeyGesture(
    Key.B,
    ModifierKeys.Control);

ApplicationCommands.Open.InputGestures.Add(OpenCmdKeyGesture);
Dim OpenCmdKeyGesture As New KeyGesture(Key.B, ModifierKeys.Control)

ApplicationCommands.Open.InputGestures.Add(OpenCmdKeyGesture)

CommandBinding

CommandBinding mengaitkan perintah dengan penangan acara yang mengimplementasikan perintah.

Kelas CommandBinding berisi Command properti, dan PreviewExecuted, Executed, , PreviewCanExecutedan CanExecute peristiwa.

Command adalah perintah yang CommandBinding sedang dikaitkan dengan. Penanganan acara yang dilampirkan ke peristiwa-peristiwa PreviewExecuted dan Executed mengimplementasikan logika perintah. Pengolah peristiwa yang dilampirkan ke PreviewCanExecute dan CanExecute menentukan apakah perintah dapat dijalankan pada target perintah saat ini.

Contoh berikut menunjukkan cara membuat CommandBinding di akar Window aplikasi. Sistem ini mengaitkan CommandBinding perintah Open dengan pengendali Executed dan CanExecute.

<Window.CommandBindings>
  <CommandBinding Command="ApplicationCommands.Open"
                  Executed="OpenCmdExecuted"
                  CanExecute="OpenCmdCanExecute"/>
</Window.CommandBindings>
// Creating CommandBinding and attaching an Executed and CanExecute handler
CommandBinding OpenCmdBinding = new CommandBinding(
    ApplicationCommands.Open,
    OpenCmdExecuted,
    OpenCmdCanExecute);

this.CommandBindings.Add(OpenCmdBinding);
' Creating CommandBinding and attaching an Executed and CanExecute handler
Dim OpenCmdBinding As New CommandBinding(ApplicationCommands.Open, AddressOf OpenCmdExecuted, AddressOf OpenCmdCanExecute)

Me.CommandBindings.Add(OpenCmdBinding)

Selanjutnya, ExecutedRoutedEventHandler dan CanExecuteRoutedEventHandler dibuat. ExecutedRoutedEventHandler membuka MessageBox yang menampilkan string yang menyatakan bahwa perintah telah dijalankan. CanExecuteRoutedEventHandler mengatur properti CanExecute ke true.

void OpenCmdExecuted(object target, ExecutedRoutedEventArgs e)
{
    String command, targetobj;
    command = ((RoutedCommand)e.Command).Name;
    targetobj = ((FrameworkElement)target).Name;
    MessageBox.Show("The " + command +  " command has been invoked on target object " + targetobj);
}
Private Sub OpenCmdExecuted(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
    Dim command, targetobj As String
    command = CType(e.Command, RoutedCommand).Name
    targetobj = CType(sender, FrameworkElement).Name
    MessageBox.Show("The " + command + " command has been invoked on target object " + targetobj)
End Sub
void OpenCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}
Private Sub OpenCmdCanExecute(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
    e.CanExecute = True
End Sub

CommandBinding dilampirkan ke objek tertentu, seperti akar Window aplikasi atau kontrol. Objek tempat CommandBinding dilampirkan menentukan cakupan pengikatan. Misalnya, CommandBinding yang dilampirkan ke leluhur sasaran perintah dapat dicapai oleh peristiwa Executed, tetapi CommandBinding yang dilampirkan ke turunan sasaran perintah tidak dapat dicapai. Ini adalah konsekuensi langsung dari cara RoutedEvent menyalurkan dan menggelembung dari objek yang memicu kejadian.

Dalam beberapa situasi, CommandBinding dilampirkan pada target perintah itu sendiri, seperti dengan TextBox class dan perintah Cut, Copy, dan Paste. Namun, lebih mudah untuk melampirkan ke leluhur CommandBinding target perintah, seperti objek utama Window atau Aplikasi, terutama jika hal yang sama CommandBinding dapat digunakan untuk beberapa target perintah. Ini adalah keputusan desain yang ingin Anda pertimbangkan ketika Anda membuat infrastruktur perintah Anda.

Sasaran Perintah

Target perintah adalah elemen tempat perintah dijalankan. Sehubungan dengan RoutedCommand, target perintah adalah elemen tempat perutean Executed dan CanExecute dimulai. Seperti yang telah disebutkan sebelumnya, di WPF, properti CommandTarget pada ICommandSource hanya berlaku ketika ICommand adalah RoutedCommand. Jika CommandTarget diatur pada ICommandSource, dan perintah yang bersesuaian bukan RoutedCommand, maka target perintah diabaikan.

Sumber perintah dapat secara eksplisit mengatur target perintah. Jika target perintah tidak ditentukan, elemen dengan fokus keyboard akan digunakan sebagai target perintah. Salah satu manfaat menggunakan elemen dengan fokus keyboard sebagai target perintah adalah memungkinkan pengembang aplikasi menggunakan sumber perintah yang sama untuk memanggil perintah pada beberapa target tanpa harus melacak target perintah. Misalnya, jika MenuItem memanggil perintah Tempel dalam aplikasi yang memiliki TextBox kontrol dan PasswordBox kontrol, target dapat berupa TextBox atau PasswordBox tergantung pada kontrol mana yang memiliki fokus keyboard.

Contoh berikut menunjukkan cara secara eksplisit mengatur target perintah dalam markup dan dalam kode di belakang.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste"
              CommandTarget="{Binding ElementName=mainTextBox}" />
  </Menu>
  <TextBox Name="mainTextBox"/>
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;
' Creating the UI objects
Dim mainStackPanel As New StackPanel()
Dim pasteTextBox As New TextBox()
Dim stackPanelMenu As New Menu()
Dim pasteMenuItem As New MenuItem()

' Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem)
mainStackPanel.Children.Add(stackPanelMenu)
mainStackPanel.Children.Add(pasteTextBox)

' Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste

The CommandManager

CommandManager menjalankan sejumlah fungsi terkait perintah. Ini menyediakan sekumpulan metode statis untuk menambahkan dan menghapus PreviewExecuted, , ExecutedPreviewCanExecute, dan CanExecute penanganan aktivitas ke dan dari elemen tertentu. Ini menyediakan sarana untuk mendaftar CommandBinding dan InputBinding objek ke kelas tertentu. CommandManager juga menyediakan sarana, melalui event RequerySuggested, untuk memberi tahu perintah kapan harus memicu event CanExecuteChanged.

Metode InvalidateRequerySuggested memaksa CommandManager untuk memicu kejadian RequerySuggested. Ini berguna untuk kondisi yang mengharuskan perintah dinonaktifkan/diaktifkan tetapi bukan kondisi yang diketahui oleh CommandManager.

Perpustakaan Perintah

WPF menyediakan sekumpulan perintah yang telah ditentukan sebelumnya. Pustaka perintah terdiri dari kelas berikut: ApplicationCommands, , NavigationCommandsMediaCommands, EditingCommands, dan ComponentCommands. Kelas-kelas ini menyediakan perintah seperti Cut, dan BrowseBackBrowseForward, Play, Stop, dan Pause.

Banyak dari perintah ini termasuk sekumpulan pengikatan input default. Misalnya, jika Anda menentukan bahwa aplikasi Anda menangani perintah salin, Anda secara otomatis mendapatkan pengikatan keyboard "CTRL+C" Anda juga mendapatkan pengikatan untuk perangkat input lainnya, seperti gerakan pena PC Tablet dan informasi ucapan.

Saat Anda mereferensikan perintah di berbagai pustaka perintah menggunakan XAML, Anda biasanya dapat menghilangkan nama kelas kelas pustaka yang mengekspos properti perintah statis. Umumnya, nama perintah tidak ambigu sebagai string, dan jenis pemilik ada untuk menyediakan pengelompokan perintah yang logis tetapi tidak diperlukan untuk disambiguasi. Misalnya, Anda dapat menentukan Command="Cut" daripada Command="ApplicationCommands.Cut" yang lebih bertele-tele. Ini adalah mekanisme praktis yang dibangun dalam prosesor WPF XAML untuk perintah (lebih tepatnya, ini adalah perilaku dari ICommand sebagai pengonversi jenis, yang dirujuk oleh prosesor WPF XAML pada waktu pemuatan).

Membuat Perintah Kustom

Jika perintah di kelas pustaka perintah tidak memenuhi kebutuhan Anda, maka Anda dapat membuat perintah Anda sendiri. Ada dua cara untuk membuat perintah kustom. Yang pertama adalah memulai dari bawah ke atas dan mengimplementasikan ICommand antarmuka. Cara lain, dan pendekatan yang lebih umum, adalah membuat RoutedCommand atau RoutedUICommand.

Untuk contoh pembuatan kustom RoutedCommand, lihat Membuat Sampel RoutedCommand Kustom.

Lihat juga