NGTweet Part 9 : Data Triggers in Silverlight

 

This is the 9th part of NGTweet series. In part 8 I demonstrated how to make use of the validation service in Silverlight. In this post I am going to demo the feature which is not natively available in Silverlight but we can accomplish it using the Microsoft.Expressions.Interactions dll. This feature is Data Trigger.

Need for Data Triggers

Sometimes there is a need to display data differently based on certain conditions. In case of NGTweet one such scenario is while displaying the profile picture for the tweet. All this while we have been displaying the users profile picture. In this post I am going to incorporate the retweet functionality. As a result we need an ability to distinguish a normal tweet and a retweet from one another. To set the context right have a look at the following screenshot

image

Under the All Friends tweets you can see the first two items in the list box. First one is a normal tweet and the second one is a retweet. I have placed the profile image of the user who retweeted the tweet over the profile image of the original user. Also the size of profile images varies in case of normal and retweeted tweets.

Those folks who have experience in WPF would be able to relate to such requirement. WPF natively supports a feature called Data Triggers which can be used to change properties dynamically based on certain values. Silverlight does not support data triggers by default.

Implement Data Triggers using Interactivity

Microsoft’s Expression Blend design tool provides a dll named Microsoft.Expression.Interactions. This dll can be used to build different markup based on certain condition. In our case the condition is based on the fact that the tweet that we are rendering is either a normal tweet or a retweet. We need some mechanism to identify this. So in our data model I added some properties which can be used during the data binding.

On the service side, I added the ability to retweet an original tweet. This is a very simple modification wherein a new method has been added to the service. I won’t show the code here because its just a wrapper over the TweetSharp API.

As can be seen from the above screenshot, there is a new image button appearing at the bottom of each tweet. This image is used to retweet the original tweet. If a tweet is retweeted, then in our data model, we’ll find a property named RetweetedStatus would have a value assigned to it. We use this to determine the value of IsRetweet

        public bool IsRetweet

        {

            get

            {

                return _tweeterStatus.RetweetedStatus != null;

            }

        }

Based on this property I want to set the height and width of the profile image. To display the profile image of the original user as well as the person who retweeted the tweet I modified the markup to display the two images. If the tweet has not been retweeted, the original profile image will be invisible whose visibility is controlled using a boolean to visibility converter.

                                    <Image Source="{Binding OriginalProfileImageSource, Mode=OneTime}"
                                          Visibility="{Binding IsRetweet, Converter={StaticResource converter}}"
                                          Height="50"
                                          Width="50"
                                          Margin="5"
                                          Grid.RowSpan="2"
                                          Grid.Row="0"
                                          Grid.Column="0"
                                          HorizontalAlignment="Center"
                                          VerticalAlignment="Top">
                                        <Image.Clip>
                                            <RectangleGeometry RadiusX="5"
                                                              RadiusY="5"
                                                              Rect="0,0,50,50" />
                                        </Image.Clip>
                                        <Image.Effect>
                                            <BlurEffect/>
                                        </Image.Effect>
                                    </Image
>

The profile image is always visible. But if its a normal tweet, we show the height and width to be bigger than in case of retweet. Also in case of retweet I want to give the impression that the profile image is overlaid on top of original profile image.  So we create the profile image with default properties

<Image Source="{Binding ProfileImageSource, Mode=OneTime}"
                                          x:Name="ProfileImage"
                                          Margin="15, 15, 5, 5"
                                          Grid.RowSpan="2"
                                          Grid.Row="0"
                                          Grid.Column="0">
                                        <Image.Clip>
                                            <RectangleGeometry x:Name="RoundedCornerRectangle"
                                                              RadiusX="5"
                                                              RadiusY="5" />
                                        </Image.Clip>

                                    </Image
>

I have specified the default margin above. We’ll manipulate it if the tweet has been retweeted. Since we are going to manipulate this image properties, we need to give a name for this image. Also the rounded corner rectangle will depend on the size of the image, so we name that as well. To start with Interactivity we use the System.Windows.Interactivity dll. We add the following markup to start the interactivity based triggers

<i:Interaction.Triggers>

Windows Interactivity dll support EventTriggers by default. We need the Data Triggers which are available in the Microsoft.Expression.Interactions dll using the markup shown below

<ei:DataTrigger Binding="{Binding Path=IsRetweet}"
Value="True"
>

This block starts the data trigger, based on IsRetweet property when the value of IsRetweet is set to True. I set the Height of profile image as

<ei:ChangePropertyAction TargetObject="{Binding ElementName=ProfileImage}"
                                  TargetName="Height"
                                  Value="30"
                                  PropertyName="Height"
/>

Similarly I have set the other properties of profile image which includes Width, Margin, HorizontalAlignment and VerticalAlignment. Since the rounded corner rectangle’s bounds depend on the size of the image, I need to set the Rect property of the rectangle accordingly.

<ei:ChangePropertyAction TargetObject="{Binding ElementName=RoundedCornerRectangle}"
TargetName="Rect"
     Value="0,0,30,30"
     PropertyName="Rect"
/>

We need to follow the same pattern when the value is false for the IsRetweet. Because its merely changing the height from 30 to 50 and likewise I won’t show the code snippets here. You can look at it by downloading the source code.


As for the image, to appear as if they are stacked on top of one another, we put them within the same parent container. In this case the parent is a grid cell. We could use any other container like StackPanel etc. By changing the margins we get a look and feel of the stacked up images.


Conclusion


Although not very straight forward, we saw that it is possible to implement data triggers in Silverlight. There are other alternatives to using the Microsoft.Expression.Interactions dll. Many people tend to use Visual State Manager to transition to different states based on property values. Custom converters or value converter is also used to achieve similar results. I shall come up with some demo in future to demonstrate these techniques as well.


As always, I have uploaded the complete working solution to Dropbox. You can find Microsoft.Expression.Interactions dll bundled along with the MVVMLight toolkit. 


Until next time Happy Programming Smile


References


I found following articles helpful during developing the features mentioned during this post


Rounded corner Image in Silverlight - http://tonychampion.net/blog/index.php/2010/09/images-with-rounded-corners-and-drop-shadows-in-silverlight/


Data triggers - http://asimsajjad.blogspot.com/2011/07/how-to-use-datatriggers-in-silverlight.html

spacer