Click here to Skip to main content
15,894,896 members
Articles / Programming Languages / Visual Basic

Declarative Codesnippet Automation with T4 Templates

Rate me:
Please Sign up or sign in to vote.
4.77/5 (15 votes)
20 Apr 2011CPOL15 min read 56.8K   1.4K   36  
This article describes a technique for automating codesnippets which are associated with a class via attributes. This results in a declarative approach to the generation of boiler-plate code.
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
    xmlns:charts="clr-namespace:Visiblox.Charts;assembly=Visiblox.Charts"
    xmlns:ec="http://schemas.microsoft.com/expression/2010/controls"
    xmlns:telemetry="clr-namespace:SilverTrack.controls"
    xmlns:telemetryGauge="clr-namespace:SilverTrack.controls.gaugeControl">

    <!--G-Force Control-->
    <Style TargetType="telemetry:GForceControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="telemetry:GForceControl">
                    <Grid Width="175">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20"/>
                            <RowDefinition Height="2" />
                            <RowDefinition/>
                        </Grid.RowDefinitions>

                        <Border Grid.Row="0" Grid.Column="0" 
                                Background="{StaticResource YellowBackgroundImageBrush}">
                            <TextBlock Text="G-FORCE(G)"
                                       Style="{StaticResource HeaderLabelStyle}"/>
                        </Border>

                        <Grid Grid.Column="0" Grid.Row="2">
                            <charts:Chart x:Name="GForceChart" Grid.Row="1" Grid.Column="3" LegendVisibility="Collapsed"
                                          Template="{StaticResource GChart}" Canvas.ZIndex="300">
                                <charts:Chart.XAxis>
                                    <charts:LinearAxis ShowGridlines="True" MajorTickInterval="3">
                                        <charts:LinearAxis.Range>
                                            <charts:DoubleRange Minimum="-2" Maximum="2" />
                                        </charts:LinearAxis.Range>
                                    </charts:LinearAxis>
                                </charts:Chart.XAxis>
                                <charts:Chart.YAxis>
                                    <charts:LinearAxis MajorTickInterval="3" ShowGridlines="True" >
                                        <charts:LinearAxis.Range>
                                            <charts:DoubleRange Maximum="2" Minimum="-2" />
                                        </charts:LinearAxis.Range>
                                    </charts:LinearAxis>
                                </charts:Chart.YAxis>
                                <charts:Chart.Series>
                                    <charts:LineSeries ShowPoints="True" PointSize="10" PointFill="{StaticResource PrimaryYBrush}" />
                                </charts:Chart.Series>
                            </charts:Chart>

                            <TextBlock Text="LAT:" Grid.Column="3" Grid.Row="1" Height="15" HorizontalAlignment="Left" Margin="5,50,0,0" VerticalAlignment="Top" 
                                       Style="{StaticResource WhiteWidgetTextBlockStyle}" TextAlignment="Left" />
                            <TextBlock x:Name="LateralGTextBlock" Grid.Column="3" Grid.Row="1" Height="15" HorizontalAlignment="Left" Margin="28,50,0,0" VerticalAlignment="Top" 
                                       Style="{StaticResource WhiteWidgetTextBlockStyle}" TextAlignment="Left" 
                                           DataContext="{TemplateBinding Lateral}" Text="{Binding}" />
                            <TextBlock Text="LONG:" Height="15" HorizontalAlignment="Left" Margin="94,2,0,0" VerticalAlignment="Top" 
                                       Style="{StaticResource WhiteWidgetTextBlockStyle}" TextAlignment="Left" />
                            <TextBlock x:Name="LongitudinalGTextBlock" Height="15" HorizontalAlignment="Left" Margin="127,2,0,0" VerticalAlignment="Top" 
                                       Style="{StaticResource WhiteWidgetTextBlockStyle}" TextAlignment="Left" 
                                           DataContext="{TemplateBinding Long}" Text="{Binding}" />
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="telemetry:ThrottleBrakeControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="telemetry:ThrottleBrakeControl">
                    <Grid Width="130">

                        <Grid.RowDefinitions>
                            <RowDefinition Height="20"/>
                            <RowDefinition Height="2"/>
                            <RowDefinition/>
                            <RowDefinition Height="2"/>
                        </Grid.RowDefinitions>

                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition MaxWidth="35"/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>

                        <Border Grid.Row="0" Grid.Column="0" Background="{StaticResource YellowBackgroundImageBrush}" Grid.ColumnSpan="5">
                            <TextBlock Style="{StaticResource HeaderLabelStyle}" Text="THROTTLE/BRAKE(%)"/>
                        </Border>

                        <Border x:Name="ThrottleContainerBorder" Grid.Column="0" Grid.Row="2" BorderThickness="2" BorderBrush="Black" Background="{StaticResource ThrottleBackgroundBrush}">
                            <Rectangle x:Name="ThrottleRectangle" DataContext="{TemplateBinding Throttle}" VerticalAlignment="Bottom" Fill="{StaticResource SecondaryYBrush}" StrokeThickness="1" Stroke="Black" />
                        </Border>

                        <TextBlock x:Name="ThrottleLabel" Text="0.0" VerticalAlignment="Center" Grid.Row="2" Grid.Column="0"
                                           DataContext="{TemplateBinding Throttle}" Style="{StaticResource WhiteWidgetTextBlockStyle}" FontWeight="Bold"/>

                        <TextBlock Grid.Column="1" VerticalAlignment="Top" Grid.Row="2" Style="{StaticResource WhiteWidgetTextBlockStyle}" FontWeight="Bold" Text="100"/>
                        <TextBlock Grid.Column="1" Grid.Row="2" VerticalAlignment="Bottom" HorizontalAlignment="Center" Style="{StaticResource WhiteWidgetTextBlockStyle}" FontWeight="Bold" Text="0"/>

                        <Border x:Name="BrakeContainerBorder" Grid.Column="2" Grid.Row="2" BorderThickness="2" BorderBrush="Black" Background="{StaticResource ThrottleBackgroundBrush}">
                            <Rectangle x:Name="BrakeRectangle" DataContext="{TemplateBinding Brake}" VerticalAlignment="Bottom" Fill="{StaticResource PrimaryYBrush}" StrokeThickness="1" Stroke="Black" />
                        </Border>

                        <TextBlock x:Name="BrakeLabel" Text="0.0" Grid.RowSpan="3" VerticalAlignment="Center" Grid.Row="2" Grid.Column="2"
                                          DataContext="{TemplateBinding Brake}" Style="{StaticResource WhiteWidgetTextBlockStyle}" FontWeight="Bold"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="telemetry:CarLocationControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="telemetry:CarLocationControl">
                    <Grid Width="440">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20"/>
                            <RowDefinition Height="2" />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Border Grid.Row="0" Grid.Column="0" Background="{StaticResource YellowBackgroundImageBrush}">
                            <TextBlock Style="{StaticResource HeaderLabelStyle}" Text="CAR LOCATION ON TRACK"/>
                        </Border>
                        <Grid Grid.Row="2">
                            <Path x:Name="path" Data="M527,118.33334 C527,118.33334 395,124.66699 368.66666,124.66699 C342.33331,124.66699 339.33295,126.33323 329.66626,124.99996 C319.99957,123.6667 310.66586,116.33375 313.33255,
                          108.33411 C315.99924,100.33447 333.99969,89.002327 348.33304,89.002327 C362.66638,89.002327 366.33307,106.66787 380.3331,100.66825 C394.33313,94.668633 425.6665,78.336334 442.33319,78.336334 C458.99988,
                          78.336334 463.99991,81.003136 484.6666,76.670113 C505.33328,72.337082 570.66675,53.337933 580.33344,53.671242 C590.00012,54.004555 595.00049,60.337803 595.00049,67.004013 C595.00049,73.670227 598.66718,
                          77.336647 609.33386,77.336647 C620.00055,77.336647 627.33423,77.003334 634.00092,79.669823 C640.6676,82.336311 652.66766,88.335899 637.33423,100.33508 C622.00085,112.33426 600.33398,112.66757 589.33392,
                          113.6675 C578.33386,114.66743 527,118.33334 527,118.33334 z" Margin="0" Stretch="Uniform" UseLayoutRounding="False" Stroke="White" StrokeThickness="2"/>
                            <ec:PathListBox x:Name="pathListBox" DataContext="{TemplateBinding Position}" Margin="0">
                                <ec:PathListBox.LayoutPaths>
                                    <ec:LayoutPath x:Name="PositionLayoutPath" SourceElement="{Binding ElementName=path}" Start="{Binding Path=Position}"/>
                                </ec:PathListBox.LayoutPaths>
                                <Ellipse x:Name="CarEllipse" Height="10" Width="10"  Fill="{StaticResource PrimaryYBrush}" />
                            </ec:PathListBox>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--Gauge Control. See http://www.codeproject.com/Articles/103035/Developing-a-very-Lookless-Silverlight-Radial-Gaug.aspx--> 
    
    <telemetryGauge:AngleToPointConverter x:Key="AngleToPointConverter"/>
    <telemetryGauge:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
    <telemetryGauge:ScaleFactorConverter x:Key="ScaleFactorConverter"/>

    <Style TargetType="telemetryGauge:GaugeControl">
        <Setter Property="FontSize" Value="10"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="telemetryGauge:GaugeControl">
                    <Grid x:Name="LayoutRoot" >
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20"/>
                            <RowDefinition Height="2"/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        
                        <!-- dial background and outer border -->
                        <Border Grid.Row="0" Grid.Column="0" Background="{StaticResource YellowBackgroundImageBrush}">
                            <TextBlock Style="{StaticResource HeaderLabelStyle}" Text="SPEED(KM/H)"/>
                        </Border>
                        
                        <Grid Grid.Row="2">
                            <!-- attached the view model -->
                            <telemetryGauge:RadialGaugeControlViewModel.Attach>
                            <telemetryGauge:RadialGaugeControlViewModel/>
                            </telemetryGauge:RadialGaugeControlViewModel.Attach>
                            
                            <Ellipse x:Name="ellipse" Stretch="Fill" StrokeThickness="2" Stroke="Black" 
                                     Fill="{StaticResource SpeedometerBackgroundBrush}" Width="130"/>

                            <!-- minor ticks -->
                            <ItemsControl ItemsSource="{Binding Path=MinorTicks}"
                            VerticalAlignment="Center" HorizontalAlignment="Center">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <Canvas></Canvas>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Rectangle Fill="White" Width="1" Height="2">
                                            <Rectangle.RenderTransform>
                                                <TransformGroup>
                                                    <TranslateTransform X="-0.5" Y="-1"/>
                                                    <TranslateTransform X="0" Y="{Binding Path=Parent.GridHeight,
                                                        Converter={StaticResource ScaleFactorConverter}, ConverterParameter=-0.37}"/>
                                                    <RotateTransform Angle="{Binding Path=Angle}"/>
                                                </TransformGroup>
                                            </Rectangle.RenderTransform>
                                        </Rectangle>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>

                            <!-- major ticks -->
                            <ItemsControl ItemsSource="{Binding Path=MajorTicks}"
                            VerticalAlignment="Center" HorizontalAlignment="Center">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <Canvas></Canvas>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Rectangle Fill="White" Width="2" Height="4">
                                            <Rectangle.RenderTransform>
                                                <TransformGroup>
                                                    <TranslateTransform X="-1" Y="-2"/>
                                                    <TranslateTransform X="0"
                                              Y="{Binding Path=Parent.GridHeight, Converter={StaticResource ScaleFactorConverter}, ConverterParameter=-0.37}"/>
                                                    <RotateTransform Angle="{Binding Angle}"/>
                                                </TransformGroup>
                                            </Rectangle.RenderTransform>
                                        </Rectangle>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>

                            <!-- major labels -->
                            <ItemsControl ItemsSource="{Binding Path=MajorTicks}"
                            VerticalAlignment="Center" HorizontalAlignment="Center">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <Canvas></Canvas>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Grid Width="50" Height="20">
                                            <Grid.RenderTransform>
                                                <TransformGroup>
                                                    <TranslateTransform X="-25" Y="-10"/>
                                                    <TranslateTransform X="0"
                                              Y="{Binding Path=Parent.GridHeight, Converter={StaticResource ScaleFactorConverter}, ConverterParameter=-0.42}"/>
                                                    <RotateTransform Angle="{Binding Path=Angle}"/>
                                                </TransformGroup>
                                            </Grid.RenderTransform>
                                            <TextBlock Text="{Binding Path=Value}" Style="{StaticResource WhiteWidgetTextBlockStyle}" FontWeight="Bold" 
                               VerticalAlignment="Center"
                               HorizontalAlignment="Center">
                                            </TextBlock>
                                        </Grid>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>

                            <!-- the qualitative ranges -->
                            <ItemsControl ItemsSource="{Binding Path=Ranges}"
                            VerticalAlignment="Center" HorizontalAlignment="Center"
                            RenderTransformOrigin="0.5, 0.5"
                            Width="200" Height="200">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <Canvas/>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                                <ItemsControl.RenderTransform>
                                    <ScaleTransform ScaleX="{Binding Path=GridHeight, Converter={StaticResource ScaleFactorConverter}, ConverterParameter=0.005}"
                                  ScaleY="{Binding Path=GridHeight, Converter={StaticResource ScaleFactorConverter}, ConverterParameter=0.005}"/>
                                </ItemsControl.RenderTransform>
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Path Stroke="Black" StrokeThickness="0.5"
                          Fill="{Binding Path=Color, Converter={StaticResource ColorToBrushConverter}}">
                                            <Path.Data>
                                                <PathGeometry>
                                                    <PathGeometry.Figures>
                                                        <PathFigure IsClosed="True" 
                                    StartPoint="{Binding Path=StartAngle, Converter={StaticResource AngleToPointConverter}, ConverterParameter=60}" >
                                                            <PathFigure.Segments>
                                                                <ArcSegment Size="60,60" RotationAngle="45" IsLargeArc="False"
                                      SweepDirection="Clockwise"
                                      Point="{Binding Path=EndAngle, Converter={StaticResource AngleToPointConverter}, ConverterParameter=60}"/>
                                                                <LineSegment Point="{Binding Path=EndAngle, Converter={StaticResource AngleToPointConverter}, ConverterParameter=50}"/>
                                                                <ArcSegment Size="50,50" RotationAngle="85" IsLargeArc="False"
                                            SweepDirection="Counterclockwise"
                                            Point="{Binding Path=StartAngle, Converter={StaticResource AngleToPointConverter}, ConverterParameter=50}"/>
                                                            </PathFigure.Segments>
                                                        </PathFigure >
                                                    </PathGeometry.Figures>
                                                </PathGeometry>
                                            </Path.Data>
                                        </Path>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>

                            <!-- the needle path -->
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="3*"/>
                                    <RowDefinition Height="7*"/>
                                    <RowDefinition Height="10*"/>
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition/>
                                    <ColumnDefinition/>
                                </Grid.ColumnDefinitions>

                                <Path Stretch="Uniform"
                    Grid.Row="1" Grid.ColumnSpan="2"
                    HorizontalAlignment="Center"
                    Data="M 0,0 L 10,60 L -10, 40 L -10 -40"
                    RenderTransformOrigin="0.5,1">
                                    <Path.RenderTransform>
                                        <RotateTransform Angle="{Binding Path=ValueAngle}"/>
                                    </Path.RenderTransform>
                                    <Path.Fill>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                                            <GradientStop Color="DarkRed" Offset="0"/>
                                            <GradientStop Color="DarkRed" Offset="0.45"/>
                                            <GradientStop Color="Red" Offset="0.55"/>
                                            <GradientStop Color="Red" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Path.Fill>
                                    <Path.Effect>
                                        <DropShadowEffect Color="Black" Direction="{Binding Path=ValueAngle}"
                                      BlurRadius="3"
                                      Opacity="0.6"
                                      ShadowDepth="5"/>
                                    </Path.Effect>
                                </Path>
                            </Grid>

                            <!-- needle cover -->
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="9*"/>
                                    <ColumnDefinition Width="3*"/>
                                    <ColumnDefinition Width="9*"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="9*"/>
                                    <RowDefinition Height="3*"/>
                                    <RowDefinition Height="9*"/>
                                </Grid.RowDefinitions>

                                <Ellipse Grid.Column="1" Grid.Row="1">
                                    <Ellipse.Effect>
                                        <DropShadowEffect Color="Black" Direction="0"
                                      BlurRadius="3"
                                      Opacity="0.6"
                                      ShadowDepth="5"/>
                                    </Ellipse.Effect>
                                    <Ellipse.Fill>
                                        <RadialGradientBrush>
                                            <GradientStop Color="#FFCEC9C9" Offset="0" />
                                            <GradientStop Color="#FFA09A9A" Offset="1" />
                                        </RadialGradientBrush>
                                    </Ellipse.Fill>
                                </Ellipse>
                            </Grid>

                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Scott Logic
United Kingdom United Kingdom
I am CTO at ShinobiControls, a team of iOS developers who are carefully crafting iOS charts, grids and controls for making your applications awesome.

I am a Technical Architect for Visiblox which have developed the world's fastest WPF / Silverlight and WP7 charts.

I am also a Technical Evangelist at Scott Logic, a provider of bespoke financial software and consultancy for the retail and investment banking, stockbroking, asset management and hedge fund communities.

Visit my blog - Colin Eberhardt's Adventures in .NET.

Follow me on Twitter - @ColinEberhardt

-

Comments and Discussions