Archive

Archive for the ‘Silverlight’ Category

Clean up your code behind with behaviors

January 22, 2011 2 comments

I’ve been developing in Silverlight for the last two years now however I never got into the habit of using Expression Blend. Three weeks ago I wrote my first Phone 7 application and while developing it, I also forced myself to use blend more often. To be honest in the beginning I was not really fond of it, I could write xaml quicker by hand than by setting all the properties in blend, but then I discovered all the extras blend has to offer and I was sold. One of those extras that come with Blend are the build in behaviors for managing storyboards, and let that be the subject of this post.

First I’ll show you the xaml and code before I was using the behaviors.

<Grid>
    <Grid.Resources>
       <Storyboard x:Name="SocialSubShowSb">
            <DoubleAnimation x:Name="SocialSubShowAnim" Duration="00:00:00.30" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="SocialSubscriptionDataContainer" d:IsOptimized="True" />
       </Storyboard>

      <Storyboard x:Name="SocialSubHideSb"><br />
            <DoubleAnimation x:Name="SocialSubHideAnim" Duration="00:00:00.30" To="-700" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="SocialSubscriptionDataContainer" d:IsOptimized="True" />
        </Storyboard>

   </Grid.Resources>
   <Grid.RowDefinitions>
          <RowDefinition Height="auto" />
          <RowDefinition Height="auto" />
    </Grid.RowDefinitions>
    
    <controls:YesNoToggleSwitch x:Name="tsSocialSub" Grid.Row="0" Header="{Binding Interpreter.SocialSubscription, Source={StaticResource AppResourceLocator}}" Style="{StaticResource ToggleSwitchStyle}" IsChecked="{Binding HasSocialSubscription, Mode=TwoWay}">  </controls:YesNoToggleSwitch>

    <Grid x:Name="SocialSubscriptionDataContainer" Grid.Row="1" Margin="15 0 0 0" Visibility="Collapsed" RenderTransformOrigin="0.5 0.5">
        <Grid.RenderTransform>
           <CompositeTransform TranslateX="-700" />
        </Grid.RenderTransform>
        <Grid.RowDefinitions>
           <RowDefinition Height="auto" />
           <RowDefinition Height="auto" />
           <RowDefinition Height="auto" />
        </Grid.RowDefinitions>

        <toolkit:ListPicker Grid.Row="0" Header="{Binding Interpreter.TypeOfTransportation, Source={StaticResource AppResourceLocator}}"                             ItemsSource="{Binding TypesOfTransport}" SelectedItem="{Binding SelectedTypeOfTransport, Mode=TwoWay}" Style="{StaticResource ListPickerStyle}" FullModeHeader="{Binding Interpreter.TypeOfTransportation, Source={StaticResource AppResourceLocator}}" />

        <TextBlock Grid.Row="1" Text="{Binding Interpreter.SocialSubscriptionMonthlyAmount, Source={StaticResource AppResourceLocator}}" Style="    {StaticResource PhoneTextSubtleStyle}" />
            
       <TextBox x:Name="txtSocialSubMonthAmount" Grid.Row="2" Text="{Binding SocialSubscriptionMonthlyAmount, Mode=TwoWay}" Style="{StaticResource NumberTextboxStyle}" InputScope="TelephoneNumber" />
      </Grid>
</Grid>

public partial class Advantages
{
   public Advantages()
   {
      InitializeComponent();
      SocialSubHideSb.Completed += delegate
            {
                SocialSubscriptionDataContainer.Visibility = Visibility.Collapsed;
            };
      ViewModel.PropertyChanged += OnViewModelPropertyChanged;
   }
   
   private AdvantagesViewModel ViewModel
   {
       get { return (AdvantagesViewModel)DataContext; }
   }
   
   private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
   {
       if (e.PropertyName == "HasSocialSubscription")
       {
            if (ViewModel.HasSocialSubscription)
            {
              SocialSubscriptionDataContainer.Visibility = Visibility.Visible;
              SocialSubShowSb.Begin();
             }
             else
             {
               SocialSubHideSb.Begin();
              }
        }
     }
}

Basically what this code does is, when the toggleswitch gets checked the ‘SocialSubscriptionDataContainer’ will become visible and slide in from the left. When the toggleswitch gets unchecked the ‘SocialSubscriptionDataContainer’ will slide out of view to the left and when this animation is completed it will collapse.

Now lets rewrite this by using behaviors.

<Grid>
    <Grid.Resources>
       <Storyboard x:Name="SocialSubShowSb">
            <DoubleAnimation x:Name="SocialSubShowAnim" Duration="00:00:00.30" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="SocialSubscriptionDataContainer" d:IsOptimized="True" />
       </Storyboard>
       <Storyboard x:Name="SocialSubHideSb">
            <DoubleAnimation x:Name="SocialSubHideAnim" Duration="00:00:00.30" To="-700" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="SocialSubscriptionDataContainer" d:IsOptimized="True" />
        </Storyboard>
   </Grid.Resources>
     <Grid.RowDefinitions>
          <RowDefinition Height="auto" />
          <RowDefinition Height="auto" />
     </Grid.RowDefinitions>

     <controls:YesNoToggleSwitch x:Name="tsSocialSub" Grid.Row="0" Header="{Binding Interpreter.SocialSubscription, Source={StaticResource AppResourceLocator}}"   Style="{StaticResource ToggleSwitchStyle}" IsChecked="{Binding HasSocialSubscription, Mode=TwoWay}">
           <i:Interaction.Triggers>
             <i:EventTrigger EventName="Checked">
               <ic:ChangePropertyAction PropertyName="Visibility" TargetName="SocialSubscriptionDataContainer" Value="Visible" />
                 <im:ControlStoryboardAction ControlStoryboardOption="Play" Storyboard="{StaticResource SocialSubShowSb}" />
                </i:EventTrigger>
                <i:EventTrigger EventName="Unchecked">
                  <im:ControlStoryboardAction ControlStoryboardOption="Play" Storyboard="{StaticResource SocialSubHideSb}" />
                </i:EventTrigger>
                <im:StoryboardCompletedTrigger Storyboard="{StaticResource SocialSubHideSb}">
                  <ic:ChangePropertyAction PropertyName="Visibility" TargetName="SocialSubscriptionDataContainer" Value="Collapsed" />
                </im:StoryboardCompletedTrigger>
             </i:Interaction.Triggers>
        </controls:YesNoToggleSwitch>

       <Grid x:Name="SocialSubscriptionDataContainer" Grid.Row="1" Margin="15 0 0 0" Visibility="Collapsed" RenderTransformOrigin="0.5 0.5">
            <Grid.RenderTransform>
                <CompositeTransform TranslateX="-700" />
            </Grid.RenderTransform>
            <Grid.RowDefinitions>
               <RowDefinition Height="auto" />
               <RowDefinition Height="auto" />
                <RowDefinition Height="auto" />
             </Grid.RowDefinitions>

             <toolkit:ListPicker Grid.Row="0" Header="{Binding Interpreter.TypeOfTransportation, Source={StaticResource AppResourceLocator}}"                             ItemsSource="{Binding TypesOfTransport}" SelectedItem="{Binding SelectedTypeOfTransport, Mode=TwoWay}" Style="{StaticResource ListPickerStyle}" FullModeHeader="{Binding Interpreter.TypeOfTransportation, Source={StaticResource AppResourceLocator}}" />

            <TextBlock Grid.Row="1" Text="{Binding Interpreter.SocialSubscriptionMonthlyAmount, Source={StaticResource AppResourceLocator}}" Style="    {StaticResource PhoneTextSubtleStyle}" />

            <TextBox x:Name="txtSocialSubMonthAmount" Grid.Row="2" Text="{Binding SocialSubscriptionMonthlyAmount, Mode=TwoWay}" Style="{StaticResource NumberTextboxStyle}" InputScope="TelephoneNumber" />
      </Grid>
</Grid>

All changes were applied to the toggleswitch, so lets break them down.

To do the ‘slide in’ feature I’ve added an EventTrigger that will listen to the Checked event of the toggleswitch. When this event is triggered two behaviors will be executed the first one is a ChangePropertyAction that will set the visibility property of the SocialSubscriptionContainer to Visible. The second one is a ControlStoryboardAction that will start the ‘SocialSubShowSb’ storyboard.

The ‘slide out’ feature requires two triggers. The first one is an EventTrigger that will listen to the Unchecked event of the toggleswitch. This trigger will execute ControlStoryboardAction that will start the ‘SocialSubHideSb’ storyboard. The second trigger is a StoryboardCompletedTrigger that is configured to listen to the Completed event of the ‘SocialSubHideSb’ storyboard. When this trigger is executed a ChangePropertyAction is called that will set the visibility of the SocialSubscriptionContainer to Collapsed.

No lets have a look at the code behind

   public partial class Advantages
    {
        public Advantages()
        {
            InitializeComponent();
        }
    }

Woo hoo no code behind!

Categories: Phone 7, Silverlight
Follow

Get every new post delivered to your Inbox.