Megosztás a következőn keresztül:


Parancsok áttekintése

A parancsolás a Windows Presentation Foundation (WPF) egyik bemeneti mechanizmusa, amely az eszköz bemeneténél szemantikaiabb szinten biztosítja a bemenetek kezelését. A parancsok közé tartoznak például a másolási, kivágási és beillesztési műveletek, amelyek számos alkalmazásban megtalálhatók.

Ez az áttekintés meghatározza, hogy mely parancsok vannak a WPF-ben, mely osztályok tartoznak a parancsmodellhez, és hogyan használhatók és hozhatók létre parancsok az alkalmazásokban.

Ez a témakör a következő szakaszokat tartalmazza:

Mik azok a parancsok?

A parancsoknak több célja is van. Az első cél a szemantika és a parancsot meghívó objektum elkülönítése a parancsot végrehajtó logikától. Ez lehetővé teszi, hogy több és eltérő forrás is meghívja ugyanazt a parancslogikát, és lehetővé teszi a parancslogika testreszabását különböző célokhoz. A sok alkalmazásban található Másolás, Kivágás és Beillesztés szerkesztési műveletek például különböző felhasználói műveletek használatával hívhatók meg, ha parancsokkal implementálják őket. Előfordulhat, hogy egy alkalmazás lehetővé teszi a felhasználó számára a kijelölt objektumok vagy szövegek kivágását egy gombra kattintva, egy menü egyik elemének kiválasztásával vagy egy billentyűkombináció, például a CTRL+X billentyűkombinációval. Parancsok használatával minden felhasználói művelettípust ugyanahhoz a logikához köthet.

A parancsok másik célja, hogy jelezze, hogy elérhető-e egy művelet. Ha folytatni szeretné egy objektum vagy szöveg kivágásának példáját, a műveletnek csak akkor van értelme, ha valami ki van jelölve. Ha egy felhasználó anélkül próbál kivágni egy objektumot vagy szöveget, hogy nincs kijelölve semmi, semmi sem történne. Ha ezt a felhasználónak szeretné jelezni, számos alkalmazás letiltja a gombokat és a menüelemeket, hogy a felhasználó tudja, lehetséges-e műveletet végrehajtani. A parancs a CanExecute metódus implementálásával jelezheti, hogy egy művelet lehetséges-e. Egy gomb feliratkozhat az CanExecuteChanged eseményre, és letiltható, ha a CanExecute visszatér false, vagy engedélyezett, ha a CanExecute visszatér true.

A parancs szemantikája konzisztens lehet az alkalmazásokban és osztályokban, de a művelet logikája az adott objektumra jellemző. A CTRL+X billentyűkombináció meghívja a Kivágás parancsot szövegosztályokban, képosztályokban és webböngészőkben, de a Kivágás művelet végrehajtásának tényleges logikáját a kivágást végrehajtó alkalmazás határozza meg. Az A RoutedCommand lehetővé teszi az ügyfelek számára a logika implementálását. A szövegobjektumok kivághatják a kijelölt szöveget a vágólapra, míg egy képobjektum kivághatja a kijelölt képet. Amikor egy alkalmazás kezeli az Executed eseményt, hozzáféréssel rendelkezik a parancs céljához, és a cél típusától függően megfelelő műveletet hajthat végre.

Egyszerű parancs példa a WPF-ben

A parancsok WPF-ben való használatának legegyszerűbb módja az, ha az egyik parancstárosztályból előre definiált RoutedCommand parancsot használ; olyan vezérlőt használ, amely natív támogatást nyújt a parancs kezeléséhez, és olyan vezérlőt használ, amely natív támogatást nyújt a parancsok meghívásához. A Paste parancs az osztály egyik előre definiált parancsa ApplicationCommands . A TextBox vezérlő beépített logikával kezeli a Paste parancsot. Az MenuItem osztály natív támogatást nyújt a parancsok meghívásához.

Az alábbi példa bemutatja, hogyan állíthat be egy MenuItem-t úgy, hogy kattintásra meghívja a Paste parancsot egy TextBox-on, feltéve, hogy a TextBox van billentyűzeti fókuszban.

<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

A WPF-parancsolás négy fő fogalma

A WPF-ben az irányított parancsmodell négy fő fogalomra bontható: a parancsra, a parancsforrásra, a parancscélra és a parancskötésre:

  • A parancs a végrehajtandó művelet.

  • A parancsforrás az az objektum, amely meghívja a parancsot.

  • A parancs célja az az objektum, amelyen a parancs végrehajtása folyamatban van.

  • A parancskötés az az objektum, amely leképzi a parancslogikát a parancsra.

Az előző példában a Paste parancs a parancs, az MenuItem a parancsforrás, a TextBox parancscél, a parancskötés pedig a TextBox vezérlő által. Érdemes megjegyezni, hogy nem mindig a vezérlő adja meg a CommandBinding, amely a parancs célosztályaként szolgál. Gyakran az alkalmazás fejlesztőjének kell létrehoznia CommandBinding, vagy a CommandBinding a parancscél valamelyik elődjéhez lehet csatolva.

Parancsok

A WPF-ben a parancsok az ICommand interfész implementálásával jönnek létre. ICommandkét metódust és ExecuteCanExecuteegy eseményt CanExecuteChangedtesz elérhetővé. Execute végrehajtja a parancshoz társított műveleteket. CanExecute meghatározza, hogy a parancs végrehajtható-e az aktuális parancscélon. CanExecuteChanged akkor jön létre, ha a parancskezelő, amely központosítja a parancsműveleteket, olyan változást észlel a parancsforrásban, amely érvényteleníthet egy olyan parancsot, amelyet a parancskötés még nem hajtott végre. A WPF implementációja ICommand az RoutedCommand osztály, és ennek az áttekintésnek a középpontjában áll.

A WPF fő bemeneti forrásai az egér, a billentyűzet, a szabadkévek és az irányított parancsok. Minél inkább berendezés-orientált bemeneteket használnak, egy RoutedEvent jelzi az alkalmazásoldal objektumainak, hogy egy bemeneti esemény történt. A RoutedCommand nem más. A Execute parancsok és CanExecute metódusok RoutedCommand nem tartalmazzák a parancs alkalmazáslogikáját, hanem olyan irányított eseményeket emelnek ki, amelyek alagutat és buborékot képeznek az elemfán, amíg egy objektummal nem találkoznak.CommandBinding A CommandBinding tartalmazza ezen események kezelőit, és ezek a kezelők hajtják végre a parancsot. Az esemény-útválasztásról a WPF-ben további információt az Irányított események áttekintése című témakörben talál.

A Execute metódus egy RoutedCommand parancspéldányon a parancscélon lévő eseményeket és PreviewExecuted eseményeket emeli Executed ki. A CanExecute metódus egy RoutedCommand parancspéldányon növeli a CanExecute parancscél eseményeit és PreviewCanExecute eseményeit. Ezek az események alagutat és buborékot az elemfán haladnak végig, amíg olyan objektummal nem találkoznak, amely rendelkezik az CommandBinding adott parancshoz.

A WPF több osztályra kiterjedő, gyakran irányított parancsokat biztosít: MediaCommands, ApplicationCommands, NavigationCommands, ComponentCommandsés EditingCommands. Ezek az osztályok csak az RoutedCommand objektumokból állnak, és nem a parancs implementálási logikáiból. A végrehajtási logika annak az objektumnak a felelőssége, amelyen a parancsot végrehajtják.

Parancsforrások

A parancsforrás az az objektum, amely meghívja a parancsot. A parancsforrások például a következők MenuItem: , Buttonés KeyGesture.

A WPF parancsforrásai általában implementálják a ICommandSource felületet.

ICommandSource három tulajdonságot tesz elérhetővé: Command, CommandTargetés CommandParameter:

A implementálható ICommandSource WPF-osztályok a következőkButtonBase: , MenuItemHyperlinkés InputBinding. ButtonBase, MenuItem és Hyperlink parancsot hív meg, amikor rájuk kattintanak, és egy InputBinding parancsot hív meg, amikor a hozzá társított InputGesture végrehajtásra kerül.

Az alábbi példa bemutatja, hogyan használhat egy MenuItem in a ContextMenu parancsot parancsforrásként Properties .

<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

A parancsforrás általában figyeli az eseményt CanExecuteChanged . Ez az esemény tájékoztatja a parancs forrását, hogy a parancs végrehajtása az aktuális parancscélon megváltozott. A parancsforrás a RoutedCommand metódus használatával lekérdezheti a CanExecute aktuális állapotát. A parancsforrás ezután letilthatja magát, ha a parancs nem hajtható végre. Erre példa a MenuItem szürkévé válása, amikor egy parancs nem hajtható végre.

Parancsforrásként InputGesture használható. A WPF-ben kétféle beviteli kézmozdulat létezik: a KeyGesture és a MouseGesture. Úgy gondolhat a KeyGesture-re, mint egy billentyűparancsra, például a CTRL+C. Az KeyGesture egy Key-ből és egy halmaz ModifierKeys-ből áll. A MouseGesture egy MouseAction-ből és egy választható ModifierKeys készletből áll.

Ahhoz, hogy egy parancsforrásként InputGesture működjön, hozzá kell rendelni egy parancshoz. Ezt többféleképpen is meg lehet valósítani. Ennek egyik módja egy InputBinding.

Az alábbi példa bemutatja, hogyan hozhat létre egy KeyBinding és egy KeyGestureközöttRoutedCommand.

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

A InputGesture társításának a RoutedCommand másik módja az, ha hozzáadjuk a InputGesture elemet a InputGestureCollectionRoutedCommand-hoz.

Az alábbi példa bemutatja, hogyan adhat hozzá egy KeyGesture-t a InputGestureCollection-hez egy RoutedCommand-nek.

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

A CommandBinding parancsot társítja a parancsot implementáló eseménykezelőkkel.

Az CommandBinding osztály tartalmaz egy tulajdonságot Command és PreviewExecutedExecuted, , PreviewCanExecuteés CanExecute eseményeket.

Command az a parancs, amelyhez a CommandBinding rendszer társítva van. Az eseménykezelők, amelyek a parancslogikához vannak csatolva, és PreviewExecuted az Executed események implementálják a parancslogikát. A PreviewCanExecute és CanExecute eseményekhez társított eseménykezelők határozzák meg, hogy a parancs végrehajtható-e a jelenlegi parancscélon.

Az alábbi példa bemutatja, hogyan hozhat létre egy CommandBinding egy alkalmazás gyökerén Window. A CommandBinding a Open parancsot társítja a Executed és CanExecute kezelőkkel.

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

Ezután létrejön az ExecutedRoutedEventHandler és a CanExecuteRoutedEventHandler . A ExecutedRoutedEventHandler ekkor megnyit egy MessageBox feliratot, amely jelzi, hogy a parancs végrehajtása megtörtént. A CanExecuteRoutedEventHandler a CanExecute tulajdonságot trueértékre állítja.

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

Az A CommandBinding egy adott objektumhoz van csatolva, például az alkalmazás gyökeréhez Window vagy egy vezérlőhöz. A kötés hatókörét a CommandBinding csatolt objektum határozza meg. Például egy CommandBinding amely a parancscél egy őséhez van csatolva, elérhető az Executed esemény által, de egy CommandBinding, amely a parancscél leszármazottjához van csatolva, nem érhető el. Ez közvetlen következménye annak, ahogyan az RoutedEvent viselkedik és terjed az eseményt kiváltó objektumból.

Bizonyos esetekben a CommandBinding közvetlenül a parancs céljához van csatolva, például az TextBox osztályhoz, valamint a Cut, Copy és Paste parancsokhoz. Gyakran azonban kényelmesebb, ha a parancscél egy őséhez, például a fő CommandBinding-hoz vagy az Alkalmazás objektumhoz kapcsoljuk a Window-t, különösen akkor, ha ugyanaz a CommandBinding több parancscélhoz is használható. Ezeket a tervezési döntéseket érdemes megfontolni a parancsinfrastruktúra létrehozásakor.

Parancscél

A parancs célja az az elem, amelyen a parancs végrehajtása történik. Ami a RoutedCommand-ot illeti, a parancs célja az az elem, amelynél az Executed és CanExecute útválasztás elindul. Ahogy korábban említettük, a WPF-ben a CommandTarget tulajdonság a ICommandSource-on csak akkor alkalmazható, ha a ICommand egy RoutedCommand. Ha a CommandTarget parancs be van állítva, ICommandSource és a megfelelő parancs nem egy RoutedCommand, akkor a parancscél figyelmen kívül lesz hagyva.

A parancsforrás explicit módon beállíthatja a parancscélt. Ha a parancscél nincs definiálva, a rendszer a billentyűzetfókuszú elemet használja a parancscélként. A billentyűzetfókuszú elem parancscélként való használatának egyik előnye, hogy lehetővé teszi, hogy az alkalmazásfejlesztő ugyanazt a parancsforrást használja egy parancs több célon való meghívásához anélkül, hogy nyomon kellene követnie a parancscélt. Ha például egy MenuItem vezérlővel és vezérlővel rendelkező TextBox alkalmazásban meghívja a PasswordBox parancsot, a cél lehet a TextBox billentyűzetfókusz, vagy PasswordBox attól függően, hogy melyik vezérlőelem fókusza van.

Az alábbi példa bemutatja, hogyan állíthatja be explicit módon a parancscélt a korrektúrában és a mögöttes kódban.

<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

A CommandManager

A CommandManager parancs számos parancshoz kapcsolódó függvényt szolgál ki. Statikus módszereket kínál az PreviewExecuted, Executed, PreviewCanExecute és CanExecute eseménykezelők hozzáadására és eltávolítására egy adott elemen. Lehetővé teszi CommandBinding és InputBinding objektumok egy adott osztályba való regisztrálását. CommandManager eszközt ad a RequerySuggested eseményen keresztül egy parancs értesítésére, amikor el kell indítania a CanExecuteChanged eseményt.

A InvalidateRequerySuggested metódus kényszeríti az CommandManager objektumot, hogy felvesse a RequerySuggested eseményt. Ez olyan feltételek esetén hasznos, amelyek letiltják/engedélyezik a parancsokat, de nem azok a feltételek, amelyekről a CommandManager rendszer tud.

Parancsgyűjtemény

A WPF előre definiált parancsokat biztosít. A parancstár a következő osztályokból áll: ApplicationCommands, NavigationCommands, MediaCommands, EditingCommandsés a ComponentCommands. Ezek az osztályok olyan parancsokat biztosítanak, mint az Cut, BrowseBack és BrowseForward, Play, Stopés Pause.

Ezen parancsok közül számos alapértelmezett bemeneti kötést tartalmaz. Ha például azt adja meg, hogy az alkalmazás kezeli a másolási parancsot, automatikusan megkapja a "CTRL+C" billentyűkombinációt. Emellett kötéseket is kap más beviteli eszközökhöz, például táblagépes tollmozdulatokhoz és beszédinformációkhoz.

Amikor az XAML használatával hivatkozik a különböző parancstárak parancsaira, általában kihagyhatja annak a könyvtárosztálynak az osztálynevét, amely a statikus parancstulajdonságot teszi elérhetővé. Általában a parancsnevek karakterláncként egyértelműek, és a tulajdonosi típusok a parancsok logikai csoportosításához léteznek, de nem szükségesek az egyértelműséghez. Megadhatja például a Command="Cut" a részletesebb Command="ApplicationCommands.Cut" helyett. Ez egy kényelmi mechanizmus, amely a WPF XAML processzorba van beépítve a parancsokhoz (pontosabban ez a típuskonverter viselkedése ICommand, amelyre a WPF XAML processzor hivatkozik a betöltési időben).

Egyéni parancsok létrehozása

Ha a parancstár-osztályok parancsai nem felelnek meg az igényeinek, létrehozhat saját parancsokat. Egyéni parancsok kétféleképpen hozhatók létre. Az első az, hogy az alapoktól kezdjük, és megvalósítjuk a ICommand interfészt. A másik módszer, és a gyakoribb megközelítés az, hogy hozzon létre egy RoutedCommand vagy egy RoutedUICommand.

Az egyéni RoutedCommandlétrehozásra példa: Custom RoutedCommand Minta létrehozása.

Lásd még