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