Windows 8.1 Blend behavior CallmethodAction

Mit Expression Blend sind zu Silverlight 3 Zeiten (oder doch schon früher?) Verhalten (englisch behavior) eingeführt worden. Damit lassen sich über Attribute oder Subelemente komplett neue Funktion zu einem UI Element hinzufügen. Das ganze in Blend per Drag&Drop. So kann ein Button mit dem passenden Behavior MouseDragElementBehavior mit der Maus bewegt werden.

Behaviors haben nun auch in Windows 8.1 Einzug gehalten. Speziell im Zusammenhang mit MVVM wurde dies gefordert. Sowohl Anzahl, als auch Implementierung unterscheiden sich erheblich zu Silverlight oder WPF. Unter anderem finden sich die Gründe dafür in der WinRT und den Regeln zur Vererbung über API Grenzen.

In diesem VB.NET Beispiel wird aus einer Liste per Geste ein Eintrag in eine andere Liste übernommen. Für die Bindung an eine ICommand basierte Eigenschaft aus dem Viewmodel, kann nur auf das Command Attribut gebunden werden. Nur wenige UI Elemente haben dieses. Hier soll eine Border und das spezielle Event Manipulationstarted verwendet werden. Da bleibt nur der CallMethodAction Eventtrigger.

Das sehr einfach gehaltene Viewmodell beinhaltet zwei Listen und eine Methode um einen Eintrag anzulegen.

   1:  Public Class listVM
   2:      Public Property namen As ObservableCollection(Of String)
   3:      Public Property ziel As ObservableCollection(Of String)
   4:      Public Sub New()
   5:          ziel = New ObservableCollection(Of String)
   6:          namen = New ObservableCollection(Of String)
   7:          namen.Add("hannes")
   8:          namen.Add("franz")
   9:          namen.Add("anna")
  10:          namen.Add("dora")
  11:          namen.Add("norbert")
  12:          namen.Add("meila")
  13:          namen.Add("nina")
  14:   
  15:      End Sub
  16:      Public Sub addziel(sender As Object, e As ManipulationStartedRoutedEventArgs)
  17:          ziel.Add(e.OriginalSource.tag)
  18:      End Sub
  19:   
  20:  End Class

Im Gegensatz zu einem Command Binding gibt es keine Parameter um auf die Daten zu kommen. Ich habe mir mit dem Tag Attribut beholfen um den Wert zu halten. Der ViewModel Code enthält noch eine weitere Abhängigkeit zur View, die EventArgs.

In Expression Blend werden dann in der XAML Seite Demodaten  aus der Klasse erzeugt (hier rot umrandet) die nur zur Entwurfszeit benötigt werden.

image

Per drag und Drop können dann Felder und Listen in das XAML Formular gezogen werden. Die Darstellung umfasst dann ein Gridview mit u.a. ein Image. Um das Itemtemplate zu ändern, wird oben mit dem kleinen Pfeil rechts neben Gridview in das weitere Template “generierte Elemente” gewechselt.

image

Dann wird das Bild und ein Textblock entfernt. Dafür wird das Stackpanel in ein Border gepackt

image

Durch Click auf das kleine (noch graue Rechteck) neben der Text Eigenschaft des TextBlock Elements kann die Bindung an ein Property aus dem Viewmodel definiert werden.

image

Um auch zur Laufzeit Daten zu haben, muss die Page noch an das Viewmodell gebunden werden. Konkret die Datacontext Eigenschaft.

image

Nun fehlt nur noch die Zuordnung zur Addziel Methode. Dazu wird das behavior CallMethodAction auf das Border Element gezogen.

image

In den Eigenschaften des EventtriggerBehavior, wird der EventName, hier Manipulationstarted definiert. Damit das Event zur Laufzeit auch kommt, nicht vergessen ManipulationMode von Border zu setzen.

image

In den Eigenschaften von CallMethodAction  wird das UI Element festgelegt, das den Context für die Methode aus dem ViewModell hält. Auf den ersten Blick nicht ganz logisch TargetObject genannt. Das kann visuell mit der Zielscheibe und der Maus erfolgen.

image

Da das Viewmodell an den Page Context gebunden ist und man sich aber im Itemtemplate des GridView befindet, wird das nicht klappen.  Entweder man legt sich außerhalb des Gridviews ein Control um den Drag&Drop way zu beschreiten und das Ergebnis dann in das Gridview zu legen. Oder man tippt es gleich im XAML.

   1:  <Page
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:local="using:App4dragMVVM"
   5:      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   6:      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   7:      xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" 
   8:  xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
   9:      x:Class="App4dragMVVM.MainPage"
  10:      mc:Ignorable="d" x:Name="root" >
  11:      <Page.Resources>
  12:          <DataTemplate x:Key="StringTemplate">
  13:              <Grid Height="110" Width="308" Margin="10" >
  14:                  <Grid.ColumnDefinitions>
  15:                      <ColumnDefinition Width="Auto"/>
  16:                      <ColumnDefinition Width="*"/>
  17:                  </Grid.ColumnDefinitions>
  18:                  <Border Grid.Column="1" Margin="10,0,29,0"  ManipulationMode="TranslateY"
  19:                           Tag="{Binding }" 
  20:                          BorderThickness="2" BorderBrush="#FF075BF8" CornerRadius="10" 
Padding="5">
  21:                          <Interactivity:Interaction.Behaviors>
  22:                          <Core:EventTriggerBehavior EventName="ManipulationStarted">
  23:                      <Core:CallMethodAction MethodName="addziel"  
TargetObject="{Binding ElementName=root,Path=DataContext}"/>
  24:                  </Core:EventTriggerBehavior>
  25:              </Interactivity:Interaction.Behaviors>
  26:                      <Border.Background>
  27:                          <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  28:                              <GradientStop Color="Black" Offset="0"/>
  29:                              <GradientStop Color="White" Offset="1"/>
  30:                          </LinearGradientBrush>
  31:                      </Border.Background>
  32:                      <StackPanel>
  33:                          <TextBlock x:Name="textBlock" Text="{Binding Mode=OneWay}" 
Style="{StaticResource TitleTextBlockStyle}"/>
  34:              
  35:                      </StackPanel>
  36:                  </Border>
  37:              </Grid>
  38:          </DataTemplate>
  39:      </Page.Resources>
  40:      <Page.DataContext>
  41:          <local:listVM/>
  42:      </Page.DataContext>
  43:   
  44:      <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" 
d:DataContext="{d:DesignData /SampleData/listVMSampleData.xaml}">
  45:          
  46:   
  47:   
  48:          <GridView HorizontalAlignment="Left" Margin="188,49,0,0" VerticalAlignment="Top" 
Width="946" Height="301" ItemTemplate="{StaticResource StringTemplate}"
ItemsSource="{Binding namen}" IsSwipeEnabled="False" SelectionMode="Single"/>
  49:          <GridView HorizontalAlignment="Left" Margin="167,392,0,0" VerticalAlignment="Top" 
Width="984" Height="348" ItemTemplate="{StaticResource StringTemplate}" ItemsSource="{Binding ziel}" />
  50:   
  51:      </Grid>
  52:  </Page>
Kommentare sind geschlossen