Sonntag, 9. Juni 2013

LED Control in WPF

Wie ich ja schon mal berichtete, ist es in WPF recht einfach ein eigenes Control zu entwickeln. Nun möchte ich das mal anhand eines Beispiels belegen.
Ziel: Ein LED Control, bei dem es möglich ist eine beliebige Farbe vorzugeben und außerdem soll das Control in der Größe auch skalierbar sein, ohne das es an schärfe verliert.

Als erstes legen wir eine neue Klasse mit dem Namen "Led" an. Diese bekommt eine DependencyProperty mit dem Namen Color vom Typ System.Windows.Media.Color. Das ist dann später die Eigenschaft, die im XAML gesetzt werden muss, um der Led eine Farbe zu geben.

Hier die Led.cs Datei
 using System.Windows;  
 using System.Windows.Controls;  
 using System.Windows.Media;  

 namespace LedSpike  
 {  
   public class Led : Control  
   {  
     public static readonly DependencyProperty ColorProperty =  
       DependencyProperty.Register("Color", typeof(Color), typeof(Led), new PropertyMetadata(default(Color)));  
     public Color Color  
     {  
       get { return (Color)GetValue(ColorProperty); }  
       set { SetValue(ColorProperty, value); }  
     }  
     static Led()  
     {  
       DefaultStyleKeyProperty.OverrideMetadata(typeof(Led), new FrameworkPropertyMetadata(typeof(Led)));  
     }  
   }  
 }  

Jedes Control benötigt ein ContentControl, ohne dieses kann es nicht angezeigt werden. Wie man unterschiedliche Themes anlegt, habe ich hier beschrieben.

Wir legen nun erstmal den Themes Ordner in unserem Projekt an und erstellen die Generic.xaml Datei, um das Standard Template für unser Control zu erstellen.
Da das Control in verschiedenen Größen genutzt werden soll, nutzen wir eine Viewbox. Danach erstellen wir eine Ellipse und legen einen Farbverlauf fest, damit das Control auch modern aussieht. Unser Verlauf hat zwei Farben, wobei ich die eine Farbe generell mit Weiß vorbelege, um einen schimmernden Effekt zu erzeugen. Die andere Farbe habe ich an die DependencyProperty gebunden.

Hier die Themes/Generic.xaml Datei:

 <ResourceDictionary  
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
   xmlns:local="clr-namespace:LedSpike">  
   <Style TargetType="{x:Type local:Led}">  
     <Setter Property="Template">  
       <Setter.Value>  
         <ControlTemplate TargetType="{x:Type local:Led}">  
           <Viewbox>  
             <Ellipse Margin="10,10,10,10" Width="300" Height="300">  
               <Ellipse.Fill>  
                 <RadialGradientBrush Center="0.6,0.35" GradientOrigin="0.6,0.35" RadiusY="0.67" RadiusX="0.67">  
                   <RadialGradientBrush.RelativeTransform>  
                     <TransformGroup>  
                       <ScaleTransform CenterY="0.35" CenterX="0.6" ScaleY="1" ScaleX="1" />  
                       <SkewTransform AngleY="0" AngleX="0" CenterY="0.35" CenterX="0.6" />  
                       <RotateTransform Angle="-4.447" CenterY="0.35" CenterX="0.6" />  
                       <TranslateTransform X="0" Y="0" />  
                     </TransformGroup>  
                   </RadialGradientBrush.RelativeTransform>  
                   <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Color}" Offset="0.8" />  
                   <GradientStop Color="White" />  
                 </RadialGradientBrush>  
               </Ellipse.Fill>  
             </Ellipse>  
           </Viewbox>  
         </ControlTemplate>  
       </Setter.Value>  
     </Setter>  
   </Style>  
 </ResourceDictionary>  

Die Benutzung ist sehr einfach. Es bedarf lediglich einen Namespace Eintrag und das Led Element im XAML.

 <Window  
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
     xmlns:local="clr-namespace:LedSpike" x:Class="LedSpike.MainWindow"  
     Title="LED spike" Height="200" Width="200">  
   <Grid>  
     <local:Led Color="Red" />  
   </Grid>  
 </Window>  

Das Ergebnis: