Attached Behaviours, Routed Events, Routed Commands ja Drag & Drop - Luento 14
Käydään läpi Attached Properties / Behaviours, Routed Events, Routed Commands ja Drag & Drop
Luentoesimerkki (luento14.zip)
- Luentovideo (Youtube)
- tjlahton2012-03-07_1451.mp4 56.1 Mt
- tjlahton2012-03-07_1451.wmv 94.0 Mt
- tjlahton2012-03-07_1451.mp3 25.4 Mt
routed_event_malli-esimerkki (routed_event_malli.zip)
AttachedBehaviours-esimerkki (AttachedBehaviours.zip)
Commanding-esimerkki (Commanding.zip)
DragDrop-esimerkki (DragDrop.zip)
Attached Behaviours / Properties
AttachedBehaviours-esimerkki (AttachedBehaviours.zip)
Attached propertieseilla voi lisätä ominaisuuksia elementin lapsi- tai vanhenmpielementteihin kuten esim.
<DockPanel> <Button DockPanel.Dock="Top">Painike</Button> </DockPanel>
Samaan tapaan voi tehdä lähes mitä tahansa laajennoksia joita voi kytkeä mihin tahansa elementtien riippumatta xamlin elementtipuun rakenteesta.
Esimerkki apinoitu artikkelista Artikkelista:Attached behaviours in WPF
// tarkistetaan, että tekstikenttään syötetään vain numeroita public static class NumbersOnlyBehaviour { public static bool GetNumbersOnly(DependencyObject obj) { return (bool)obj.GetValue(NumbersOnlyProperty); } public static void SetNumbersOnly(DependencyObject obj, bool value) { obj.SetValue(NumbersOnlyProperty, value); } public static readonly DependencyProperty NumbersOnlyProperty = DependencyProperty.RegisterAttached("NumbersOnly", typeof(bool), typeof(NumbersOnlyBehaviour), new UIPropertyMetadata(false, OnNumbersOnlyChanged)); // Täällä tehdään varsinaiset muutokset kontrollin toiminnallisuuteen private static void OnNumbersOnlyChanged(object sender, DependencyPropertyChangedEventArgs e) { if (!(sender is TextBox)) return; TextBox textBox = (TextBox)sender; bool isNumberOnly = (bool)(e.NewValue); if (isNumberOnly) textBox.PreviewTextInput += BlockNonNumbers; else textBox.PreviewTextInput -= BlockNonNumbers; } private static void BlockNonNumbers(object sender, TextCompositionEventArgs e) { foreach (char ch in e.Text) if (!Char.IsDigit(ch)) e.Handled = true; } }
XAML:
<TextBox oma:NumbersOnlyBehaviour.NumbersOnly="True" />
Drag & Drop
DragDrop-esimerkki (DragDrop.zip)
drag drop in wpf explained end to end
- Lisää raahattavaan objektiin MouseMove tms. tapahtumankäsittelijä, joka aloittaa Drag & Drop -toiminnon
- DoDragDrop
- Määritä lähtöobjekti, raahattava tieto ja mahdolliset raahausefektit
- Jonkin elementin pitää olla raahauksen kohde (AllowDrop = True)
- Kohteessa täytyy käsitellä Drop-tapahtuma, joka ottaa vastaan raahatun tiedon (GetData )
- Tee raahatulla tiedolla jotakin
Drag & Dropin perustoiminnot voi tehdä Attached Propertyn avulla. kts. luentomalli.
Toimintaa selventää parhaiten Walkthrough: Enablind Drag and Drop on a User Control
Routed Events
routed_event_malli-esimerkki (routed_event_malli.zip)
Routed Event kulkee elementtipuussa ylös tai alaspäin eli saman tapahtuman voi käsitellä useampikin elementti eikä vain ainoastaan yksi kuten Windows Formsissa
- Tunneling - tapahtuma kulkee puussa juuresta ylöspäin eli käsittely alkaa Window-elementistä ja kulkee puuta eteenpäin kunnes päätyy lehteen (Preview-events)
- Bubbling - tapahtuma kulkee puussa sisältä kohti juuri esim. painikkeen Click-tapahtumassa painike käsittelee tapahtuman ensin ja seuraava elementti, jonka sisällä painike on jne. kunnes saavutaan juurielementtiin eli esim. Window
- Direct - tapahtuman käsittely kuten Windows Formsissa
Yleensä sama tapahtuma käsitellään tapahtumaparina eli ensimmäisenä on Tunneling-versio tapahtumasta ja sen jälkeen Bubbling-versio esim. PreviewMouseLeftButtonDown-tapahtuu ensin (Tunneling) ja myöhemmin MouseLeftButtonDown (Bubbling).
Tapahtuman voi käsitellä useampi käsittelijä. Matkan varrella tapahtumaan liittyvää dataa voidaan muuttaa. Käsittelijä voi myös ilmoittaa, että tapahtuma on käsitelty (e.Handled = True), jonka jälkeen muut eivät saa tapahtumaa enää käsittelyyn (Tämä on tosin kierrettävissä, HandleEventsToo = True).
public class OmaButton: Button { public static readonly RoutedEvent OmaEvent = EventManager.RegisterRoutedEvent( "Oma", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(OmaButton)); public event RoutedEventHandler Oma { add { AddHandler(OmaEvent, value); } remove { RemoveHandler(OmaEvent, value); } } void RaiseOmaEvent() { RoutedEventArgs newEventArgs = new RoutedEventArgs(OmaButton.OmaEvent); RaiseEvent(newEventArgs); } protected override void OnClick() { RaiseOmaEvent(); } }
EventSetter ja EventTrigger toimivat vain Routed Eventien kanssa. EventTriggereihin palataan animaatioiden yhteydessä.
Attached Events
<StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler"> <Button Name="YesButton" Width="Auto" >Yes</Button> <Button Name="NoButton" Width="Auto" >No</Button> <Button Name="CancelButton" Width="Auto" >Cancel</Button> </StackPanel>
Routed Commands
Commanding-esimerkki (Commanding.zip)
Routed Commands aktivoivat/disabloivat niihin liittyvät käyttöliittymäkontrollit automaattisesti sen perusteella ilmoittaakö niihin liittyvä käsittelijä komennon olevan käytössä tai pois käytöstä
Routed Commandeja käyttävien elementtien ei tarvitse suoraan liittyä vastaaviin käsittelijöihin
Komento:
<Button Name="komentopainike" Command="ApplicationCommands.Save">Save</Button> <Button Command="Save" CommandTarget="{Binding ElementName=komentopainike}" >Save</Button> <Window.InputBindings> <KeyBinding Key="O" Modifiers="Control" Command="ApplicationCommands.Open" /> </Window.InputBindings> <StackPanel> <Menu> <MenuItem Command="ApplicationCommands.Paste" CommandTarget="{Binding ElementName=mainTextBox}" /> </Menu> <TextBox Name="mainTextBox"/> </StackPanel> <!-- Oma komento --> <Window.CommandBindings> <CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}" Executed="ExecutedCustomCommand" CanExecute="CanExecuteCustomCommand" /> </Window.CommandBindings>
Komennon käsittelijä:
<UserControl ...> <UserControl.CommandBindings> <CommandBinding Command="ApplicationCommands.Save" CanExecute="OnCanExecute" Executed="OnExecute"/> </UserControl.CommandBindings> </UserControl>
- CanExecute määrää onko komento suoritettavissa vai ei (e.CanExecute = True;)
- Executed suorittaa varsinaisen toiminnon
KeyGesture OpenKeyGesture = new KeyGesture( Key.O, ModifierKeys.Control); KeyBinding OpenCmdKeybinding = new KeyBinding( ApplicationCommands.Open, OpenKeyGesture); this.InputBindings.Add(OpenCmdKeybinding); CommandBinding OpenCmdBinding = new CommandBinding( ApplicationCommands.Open, OpenCmdExecuted, OpenCmdCanExecute); // yhdistetään komento ikkunaan this.CommandBindings.Add(OpenCmdBinding); public static RoutedCommand CustomRoutedCommand = new RoutedCommand(); //CommandBinding customCommandBinding = new CommandBinding( // CustomRoutedCommand, ExecutedCustomCommand, CanExecuteCustomCommand); // käytetään lyhyyden vuoksi samoja metodeja mitä open-komennon kanssa CommandBinding customCommandBinding = new CommandBinding( CustomRoutedCommand, OpenCmdExecuted, OpenCmdCanExecute); this.CommandBindings.Add(customCommandBinding); Button CustomCommandButton = new Button(); CustomCommandButton.Command = CustomRoutedCommand; 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); } void OpenCmdCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; }
- Attached Behaviours in WPF
- Attached Properties
- Routed Events overview
- Understanding Routed Events and Commands In WPF
- Commanding Overview
- RoutedCommand class
- Drag & Drop Overview
- How can I drag and drop items between data bound ItemsControls?
- Wpf Drag & Drop behaviour
- Introduction to Attached Behaviors in WPF
Käyttäjien kommentit