XAML Converter und MVVM

Ich hatte mir vorgenommen einen einfachen Converter zu schreiben, bin dann aber bei einem etwas ausführlicheren VB.NET WinRT Beispiel gelandet, Mit drei Slidern wird die Hintergrundfarbe eines Rechtecks verändert. Entsprechend den Farbkanälen Rot Grün Blau.

Screenshot (37)

Das ist ein gutes Beispiel für einen Converter, weil der Typ Brush nicht mit den Integer Werten von Schiebereglern korrespondiert. Im XAML kann man Fill=”blue” schreiben. Aber hier retten einem Implizite Typ converter den Arsch und konvertieren nach Brush. Im Code geht das ohnehin nicht.

In anderen XAML Dialekten könnte man sich per Multibinding in Kombination mit Elementbinding retten. Dies wird aber in Windows 8.1 nicht unterstüzt.

Ein weiterer theoretischer Ansatz ( der nicht funktioniert) ist direkt über die Color Kanäle zu binden.

   1:   <Rectangle.Fill>
   2:         <SolidColorBrush >
   3:                <SolidColorBrush.Color>
   4:                     <Color A="255"  R="255" G="0" B="0" />
   5:          </SolidColorBrush.Color>
   6:         </SolidColorBrush>
   7:  </Rectangle.Fill>--> 

 

Visual Studio 2013 zeigt das obige XAML im Designer korrekt an, Zur Laufzeit wirft es allerdings einen Fehler, Darüber hinaus muss eine Eigenschaft, die gebunden werden soll, ein Dependencyproperty sein.

Meine Klasse ( nennen wir sie ViewModel) enhält defacto ein Farbmodell mit den Propertys rot, grün blau. Sehr oft lässt sich beim designen des Viewmodells, der Blick auf die spätere Implementierung in der Sicht (View) nicht unterdrücken. Hier werden die Slider an die Integer Werte gebunden.

Eine weitere Eigenschaft hält die dadurch gemischte Farbe, Die Farbe muss künstlich beim sliden aktualisiert werden, damit das UI auch aktualisiert wird. Dadurch wird das Event PropertyChanged ins UI gefeuert und das Rechteck ändert seine Farbe.

   1:  Imports Windows.UI
   2:  Imports Windows.UI.ColorHelper
   3:  Public Class farbeVM
   4:      Implements INotifyPropertyChanged
   5:   
   6:      Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) 
Implements INotifyPropertyChanged.PropertyChanged
   7:      Public Sub onPropertyChanged(<CallerMemberName> Optional name As String = "")
   8:          RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
   9:   
  10:      End Sub
  11:      Public Sub New()
  12:          _dieFarbe = New Color
  13:   
  14:      End Sub
  15:   
  16:   
  17:      Private _dieFarbe As Color
  18:      Public Property dieFarbe() As Color
  19:          Get
  20:   
  21:              Return _dieFarbe
  22:          End Get
  23:          Set(ByVal value As Color)
  24:              _dieFarbe = value
  25:              onPropertyChanged()
  26:          End Set
  27:      End Property
  28:      Public Sub updateColor()
  29:          dieFarbe = FromArgb(255, rot, grun, blau)
  30:      End Sub
  31:      Private _rot As Integer
  32:      Public Property rot() As Integer
  33:          Get
  34:              Return _rot
  35:          End Get
  36:          Set(ByVal value As Integer)
  37:              _rot = value
  38:               updateColor()
  39:          End Set
  40:      End Property
  41:      Private _blau As Integer
  42:      Public Property blau() As Integer
  43:          Get
  44:              Return _blau
  45:          End Get
  46:          Set(ByVal value As Integer)
  47:              _blau = value
  48:   
  49:              updateColor()
  50:          End Set
  51:      End Property
  52:      Private _grun As Integer
  53:      Public Property grun() As Integer
  54:          Get
  55:              Return _grun
  56:          End Get
  57:          Set(ByVal value As Integer)
  58:              _grun = value
  59:               updateColor()
  60:          End Set
  61:      End Property
  62:   
  63:   
  64:  End Class

Die Slider schicken direkt jede Änderung an das Viewmodel

   1:   <Slider Value="{Binding rot, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" .
.. Background="#29FF0000" Maximum="255" />
   2:  <Slider Value="{Binding grun,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" 
... Background="#2921FF00" Maximum="255"/>
   3:  <Slider Value="{Binding blau,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ..
.. Background="#290031FF" Maximum="255"/>
   4:   

Nun kommt der Konverter zum Einsatz, der aus Color einen Soldicolorbrush formt. Auch Konverter werden deklarativ im XAML instanziert. 

   1:   <Page.DataContext>
   2:          <local:farbeVM/>
   3:      </Page.DataContext>
   4:      <Page.Resources>
   5:          <local:farbeconf x:Key="konf1"/>
   6:      </Page.Resources>

Intellisense schlägt den Eintrag “farbconf” auch vor, wenn das Windows Store Projekt erfolgreich kompiliert ist. Der Converter hat zwei Methoden, die über ein Interface erzwungen werden.

   1:  Public Class farbeconf
   2:      Implements IValueConverter
   3:   
   4:   
   5:      Public Function Convert(value As Object, targetType As Type, 
   6:  parameter As Object, language As String) As Object Implements IValueConverter.Convert
   7:          Return New SolidColorBrush(value)
   8:   
   9:      End Function
  10:   
  11:      Public Function ConvertBack(value As Object, targetType As Type, 
  12:  parameter As Object, language As String) As Object Implements IValueConverter.ConvertBack
  13:   
  14:      End Function
  15:  End Class

Die Methode ConvertBack bleibt ungenutzt. Nur benötigt, wenn der Benutzer direkt im Rechteck malen könnte und damit die Slider verschoben werden sollen.

Die Bindung an die Farbe wie üblich mit Intellisense unterstützung. Da der Converter per deklaration statisch instanziert wurde, mit passenden Schlüsselwort und dem Key.

   1:   <Rectangle Fill="{Binding dieFarbe, Converter={StaticResource konf1},Mode=TwoWay}" 
Kommentare sind geschlossen