May 24, 2014

WPF - Control Templates

8 comments
In the previous post we have seen that, elements in the WPF object tree which derive from Visual constitute the visual tree. The visual tree is thus all the WPF elements that come together to render a control’s (or a set of controls’) UI to the screen. Control templates are XAML declarations of the visual tree of a control. Consider the simple case of a Button control,
 <!-- A default button -->
 <Button Height="100" Width="100" Content="Click Me!" />
</Grid>

The Button has a default visual template, i.e, a visual tree supplied by WPF. We want to override this implementation and provide our own custom UI for the button. To do this we’ll customize the Button control’s UI template (and thus it’s visual tree). This is simple enough,
<Grid>    
    <!-- A default button -->
        <Button Height="100" Width="100" Content="Click Me!">
            
            <!-- Override the Button's UI template -->
            <Button.Template>
                
                <!-- Create a new ControlTemplate that targets a Button -->
                <ControlTemplate TargetType="{x:Type Button}">

                    <!-- Override the default UI of the control with this custom UI -->
                    <Grid>
                        <Ellipse Height="100" Width="75" Stroke="Red" Fill="BlanchedAlmond" />
                        
                        <!-- Take the control's Content (which is “Click Me!”) and place here -->
                        <ContentPresenter Content="{TemplateBinding Content}" 
                           VerticalAlignment="Center" HorizontalAlignment="Center" />
                    </Grid>
                </ControlTemplate>
            </Button.Template>

        </Button>
</Grid>

As we can see from the XAML above, we’ve overridden the button’s UI template and provided our own implementation which consists of a Grid, with an Ellipse inside it and the Button’s Content inside the Ellipse. Even the height and width of the button get overridden to the new values of 100 and 75.
Default Button Custom Button

Another way to implement same thing is similar to the way we define styles in wpf, like below,
<Grid>
    <Grid.Resources>
        <!-- Define a named template, with a target type -->
        <ControlTemplate x:Key="RoundButtonTemplate" TargetType="{x:Type Button}">
            <!-- Override the default UI of the control with this custom UI -->
            <Grid>
                <Ellipse Height="100" Width="75" Stroke="Red" Fill="LightGray" />
                <!-- Take the control's Content and place here -->
                <ContentPresenter Content="{TemplateBinding Content}" 
                        VerticalAlignment="Center" HorizontalAlignment="Center" />
            </Grid>
        </ControlTemplate>
    </Grid.Resources>

    <!—- Apply the 'RoundButtonTemplate' template to this button -->
    <Button Height="100" Width="100" Content="Some Text"
            Template="{DynamicResource RoundButtonTemplate}" />

    </Grid>
Note that although we have overridden the UI, the button’s functionality remains the same, all the same events are raised and all the properties are still available. We should use TemplateBinding to allow the control to specify property values as much as possible. This is shown in XAML above for Content. Control templates also work with styles and triggers. The syntax is straightforward,
<Grid>
    <Grid.Resources>

        <!-- First ControlTemplate definition for normal button state UI -->
        <ControlTemplate x:Key="RoundButtonTemplate" TargetType="{x:Type Button}">
            <Grid>
                <Ellipse Height="60" Width="60" x:Name="MyEllipse"
                         Stroke="{TemplateBinding BorderBrush}"
                         Fill="{TemplateBinding Background}" />
                <ContentPresenter Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" />
            </Grid>
            <!-- Set a trigger to activate on mouseover -->
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="MyEllipse" Property="Fill" Value="Blue" />
                </Trigger>
            </ControlTemplate.Triggers>
         </ControlTemplate>

        <!-- Second ControlTemplate definition for clicked button state UI -–> 
        <ControlTemplate x:Key="RoundButtonPressedTemplate" TargetType="{x:Type Button}">
            <Grid>
                <Ellipse Height="60" Width="60"
                     Stroke="{TemplateBinding BorderBrush}"
                     Fill="Red" />
                <ContentPresenter Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" />
            </Grid>
        </ControlTemplate>

        <!-- Create a style definition for the button -->
        <Style x:Key="RoundButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Template" Value="{DynamicResource RoundButtonTemplate}"/>
            <Style.Triggers>
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Template" Value="{DynamicResource RoundButtonPressedTemplate}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Grid.Resources>

    <!-- Apply the 'RoundButtonStyle' to this button -->
    <Button Height="100" Width="100" Content="Text"
            Style="{DynamicResource RoundButtonStyle}"
            BorderBrush="Red" Background="LightGray" />

</Grid>

The WPF content model allows the Button’s content to be a TREE of elements. In our examples, we have set the button’s content to “Click Me!” like this,

<Button Height="100" Width="75" Content="Click Me!" />

But the button’s Content could be set to a tree, like this,

<Button Height="100" Width="75">
    <Button.Content>
        <Grid>
            <StackPanel>
                <TextBlock Text="Click Me!"/>
            </StackPanel>
        </Grid>
    </Button.Content>
</Button>

8 comments :

  1. These programming was very easily understand and more important coding are provided on this post and this is very valuable in my studies,all coding easily understand and develop more skills,thanks for sharing this post.
    ios training in chennai

    ReplyDelete
  2. great doing. and i happy to visit your blog to know about this wonderful information. thanks for sharing. keep updating.
    Salesforce Training in Chennai

    ReplyDelete
  3. Very happy to see this blog. Gives a wonderful information with coded explanaion. Thank you for this blog. very useful to me.
    Android Training in Chennai

    ReplyDelete
  4. Thanks a lot for all your valuable article! We are really happy about the your thoughts... SAP Training in chennai

    ReplyDelete
  5. That is very interesting; you are a very skilled blogger. I have shared your website in my social networks! A very nice guide. I will definitely follow these tips. Thank you for sharing such detailed article.


    SAP training in Chennai

    ReplyDelete
  6. Really very nice blog information for this one and more technical skills are improve,i like that kind of post.



    SAP training in Chennai

    ReplyDelete