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)

Attached Behaviours / Properties

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

        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

Drag & Dropin perustoiminnot voi tehdä Attached Propertyn avulla. kts. luentomalli.

Routed Events

Routed Event kulkee elementtipuussa ylös tai alaspäin eli saman tapahtuman voi käsitellä useampikin elementti eikä vain ainoastaan yksi 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(OmaControl));
 
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

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

Käyttäjien kommentit

Kommentoi tätä sivua Lisää uusi kommentti
Kurssimateriaalien käyttäminen kaupallisiin tarkoituksiin tai opetusmateriaalina ilman lupaa on ehdottomasti kielletty!
http://appro.mit.jyu.fi/gko/luennot/luento14/
© Antti Ekonoja (antti.j.ekonoja@jyu.fi) <http://users.jyu.fi/~anjoekon/>
Tommi Lahtonen (tommi.j.lahtonen@jyu.fi) <http://hazor.iki.fi/>
2012-03-22 14:06:19
Informaatioteknologia - Jyväskylän yliopiston informaatioteknologian tiedekunta