(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Forums

Search in:

Go

Silverlight 5: Changing a ControlTemplate Property dynamically

  • mk222
    mk222
    2 points
    1 posts
    Feb 10, 2012, 12:53 AM
        Report Abuse

    Hello everybody,

    I have a little problem, which keeps me going nuts now for two days. I am a XAML Rookie, but I have 5 years experience with WinForms & Co. Maybe I don't need a very deep explanation, maybe just a good example or hint would help me, but I am now at a point where I know, I need some help.

    Ok. Here is the deal:

    I have a ControlTemplate that I use for buttons. This Template has two images. The super simple thing I want to do is, to change the source of the images for every button instance in the XAML Code. The goal is simple: The whole bevavior for every button is the same, the images are different.

    This is how I use the template in XAML:

    <Button Template="{StaticResource PictureButtonTemplate}" Grid.Row="1" Height="48" HorizontalAlignment="Left" Margin="108,21,0,0" Name="button2" VerticalAlignment="Top" Width="48" Background="Black"></Button>

    And this is the ControlTemplate itself:

    <ControlTemplate x:Key="PictureButtonTemplate" TargetType="Button">
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Disabled"/>
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="Pressed"/>
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="mouseOverImage">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Visibility>Visible</Visibility>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="normalImage">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Visibility>Collapsed</Visibility>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Image x:Name="normalImage" Source="Grafiken/Icons/48x48/Man.png"           Margin="0" Stretch="Fill" HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto"/>
                <Image x:Name="mouseOverImage" Source="Grafiken/Icons/48x48/eraser_fav_48.png" Margin="0" Stretch="Fill" Visibility="Collapsed"       HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto"/> </Grid>
     </ControlTemplate>

    In the control template, you can see two images. I just want to change these images dynamically in XAML.

    How can I do this?

     BTW: I also have implemented a code behind file for this ControlTemplate. So everything is possible, I just need a hint.....

    Thank you.

    Michael, Hamburg.

     

     

    Reply

All Posts


  • Bobi Rakova
    13 points
    6 posts
    Feb 10, 2012, 11:34 AM
            Report Abuse

    Hi,

    the way I would do this is to create a very simple custom Silverlight templated control. In your case it would have two dependency properties for the two images and in the OnApplyTemplate you can set the appropriate Image sources. Later in your XAML you could say:

    <local:RolloverButtonControl Width="100" Height="100"
               NormalImageSource="searchAll.png"
               RolloverImageSource="searchEmpty.png"/>
    Make the custom control inherit from Button - that way you'll have all the button's functionality for free ;)
    And in the RolloverButtonControl control template you could have something like:

    <Style TargetType="local:RolloverButtonControl">
    <Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="local:RolloverButtonControl">
        <Border Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}">
            <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Disabled" />
                <VisualState x:Name="Normal" />
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                    Storyboard.TargetName="image">
                        <DiscreteObjectKeyFrame KeyTime="0">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                    Storyboard.TargetName="image1">
                        <DiscreteObjectKeyFrame KeyTime="0">
                            <DiscreteObjectKeyFrame.Value>
                                <Visibility>Collapsed</Visibility>
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Pressed" />
            </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid>
                <Image x:Name="image1"
                        Stretch="Fill"/>
                <Image x:Name="image"
                        Stretch="Fill"
                        Visibility="Collapsed" />
            </Grid>
        </Border>
        </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>

    And in the code for the RolloverButtonControl control I have:

    public override void OnApplyTemplate()
    {
        Image normalImage = this.GetTemplateChild( "image1" ) as Image;
        normalImage.Source = new BitmapImage( new Uri( this.NormalImageSource, UriKind.RelativeOrAbsolute ) );
     
        Image rolloverImage = this.GetTemplateChild( "image" ) as Image;
        rolloverImage.Source = new BitmapImage( new Uri( this.RolloverImageSource, UriKind.RelativeOrAbsolute ) );
     
        base.OnApplyTemplate();
    }

    It seems to work fine :) and its pretty clean.

    Reply
  • mk222
    mk222
    2 points
    1 posts
    Feb 10, 2012, 02:57 PM
            Report Abuse

    Hello Bobi Rekova,

    thank you very much! YOU MADE MY DAY. Now, that's an approach I also understand from a "WinForms programmer view". In WinForms you also just inherit from controls and override oder extend the properties.

     If you begin with XAML and read all the information you will find many style and template examples, but they never show how to extend them properly.

     For everybody, who has the same problem, here is the code that works for me now. Of course, you have to change the namespaces, but the it should work

     Here is the XAML Code for the Button Control:

    <Button x:Class="SOLID.CustomControls.RolloverButtonControl"
        xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
        mc:Ignorable="d"
        d:DesignHeight="50" d:DesignWidth="50">
     
        <Grid x:Name="Layout" Background="White">
            <Grid.Resources>
                <Style x:Name="RolloverButtonStyle" TargetType="Button">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate x:Name="RolloverButtonTemplate" TargetType="Button">
                                <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                                    <VisualStateManager.VisualStateGroups>
                                        <VisualStateGroup x:Name="CommonStates">
                                            <VisualState x:Name="Disabled" />
                                            <VisualState x:Name="Normal" />
                                            <VisualState x:Name="MouseOver">
                                                <Storyboard>
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Image_mouseOver">
                                                        <DiscreteObjectKeyFrame KeyTime="0">
                                                            <DiscreteObjectKeyFrame.Value>
                                                                <Visibility>Visible</Visibility>
                                                            </DiscreteObjectKeyFrame.Value>
                                                        </DiscreteObjectKeyFrame>
                                                    </ObjectAnimationUsingKeyFrames>
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Image_normal">
                                                        <DiscreteObjectKeyFrame KeyTime="0">
                                                            <DiscreteObjectKeyFrame.Value>
                                                                <Visibility>Collapsed</Visibility>
                                                            </DiscreteObjectKeyFrame.Value>
                                                        </DiscreteObjectKeyFrame>
                                                    </ObjectAnimationUsingKeyFrames>
                                                </Storyboard>
                                            </VisualState>
                                            <VisualState x:Name="Pressed" />
                                        </VisualStateGroup>
                                    </VisualStateManager.VisualStateGroups>
                                    <Grid>
                                        <Image x:Name="Image_normal" Width="48" Height="48" Stretch="Fill" />
                                        <Image x:Name="Image_mouseOver"  Width="48" Height="48" Stretch="Fill" Visibility="Collapsed" />
                                    </Grid>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Grid.Resources>
                    
        </Grid>
    </Button>

    Here ist the code behind for the button control:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Media.Imaging;
     
    namespace SOLID.CustomControls
    {
        public partial class RolloverButtonControl : Button
        {
            public RolloverButtonControl()
            {
                InitializeComponent();
                this.Style = this.RolloverButtonStyle;
            }
     
            public String Image_normal { get; set;}
            public String Image_mouseOver { get; set;}
     
            Image _normalImage = new Image();
            Image _mouseOverImage = new Image();
     
            public override void OnApplyTemplate()
            {
                _normalImage = this.GetTemplateChild("Image_normal") as Image;
                _normalImage.Source = new BitmapImage(new Uri(this.Image_normal, UriKind.RelativeOrAbsolute));
     
                _mouseOverImage = this.GetTemplateChild("Image_mouseOver") as Image;
                _mouseOverImage.Source = new BitmapImage(new Uri(this.Image_mouseOver, UriKind.RelativeOrAbsolute));
     
                base.OnApplyTemplate();
            }
             
        }
    }

    And here is, how I use the control in XAML. Dont' forget to import the namespace, otherwise it won't work:

    <cc:RolloverButtonControl Width="48" Height="48" Image_normal="Grafiken/Icons/48x48/Man.png" Image_mouseOver="Grafiken/Icons/48x48/Man_blue.png" Margin="108,21,0,0"/>

     

    That's it. I think, this approach works best, because now I can customize the control with events and databinding features and all the other stuff that I need!

    Thank you Bobi.....

    Greetz, Michael, hamburg.

    Reply

  • Bobi Rakova
    13 points
    6 posts
    Feb 10, 2012, 03:23 PM
            Report Abuse

    Hi Michael,

    I'm so glad that you've sorted it out! I have used custom controls in many cases and they seem to be great when you want to achieve a little bit different behavior. 
    Here are a couple of articles which are actually pretty old but still explain the main principles in more details:

    Greetings from Bulgaria :)

    Reply
Page  

To reply to this thread you must Log In to your account


Thread


Tags: 
  • Asked
    602 days ago
  • Viewed
    1675
  • Last Activity

Related Threads


Shortcuts