Get Microsoft Silverlight

Friday, May 13, 2011

WP7Dev Tip 2– Few things to remember on Image handling

Image handling is an important factor deciding the performance as well as usability of any application. When it comes to Windows Phone 7 it is even more important because of the limited network conditions and the low processing power as compared to PC.
Here is the video I am talking about the same things with a Bing Search sample in Silverlight TV show


I am just listing down few common tips which can greatly improve the performance and effectiveness of your application. And also please note that some of the points might not be applicable for certain applications especially for very small apps.
  • Use JPEG instead of PNG whenever possible – Jpeg decodes faster than PNG image.  If there is no transparency needed, use Jpeg with a compromised quality
  • Optimize your static Image quality :  Medium quality compressed Jpeg requires less memory to render as compared to a full quality Jpeg. So there is a big savings in memory and performance, if we can compromise on the Jpeg quality slightly. I am pasting two images below, one is 100% and the other is 97% quality, you can hardly make out the difference so the gist of it from a file size perspective is that the 97% one takes only half the size of the 100% image(108KB and 58Kb) ( of course the size and compression varies depends on the color information of the images). Now if you have got so many static images in the project, this trick can reduce the XAP file size considerably smaller as well as runtime memory usage will be quite less. You can consider this tip when you use large background images like Page/Panorama/Pivot background or splash screen images etc..
                   Penguins  Penguins97
  • Use images instead of complex gradients or vector graphics(XAML).
  • Never bind server-hosted images directly to the <Image> control, because Silverlight runtime will use the UI thread (using WebClient) to fetch that image from the server, that can make the UI unresponsive for some time.
  • Use a background thread and HttpWebRequest class based implementation to download the image data in an efficient way which finally creates BitmapImage and sets that as the source. A clean MVVM wrapper around this would make your entire Image management pretty easy.
  • When large scrollable list boxes need preview again don’t use vector/gradients instead use small Jpeg/png, that helps the system level caching effectively and improve the performance of scrolling.
  • Never let any image downloads happening while scrolling : Image downloading on long Listboxes should be controlled by the ScrollViewer state and position to optimize the network activity and also it would be effective to download the images in a queue based background thread system. This will ensure scrolling performance by downloading only the visible set of images, that too only when the scrolling activity stops.
In the below code snippet I have a collection of ViewModel instances bound to a ListBox and the ListBox has a ScrollViewer in its control template. We need to do two things to make sure there is no unnecessary image download happening 1) Detect the scroll stop event  2) Calculate the scroll position to find out the range of items which are visible to the user. Our aim is to just download the images associated with the ViewModels of that particular range when the scroll operation stops.
I am using the code snippet from Peter Torr’s blog for detecting the Scroll state and applying some easy math to find out the index range. Here I am assuming my Collection class has  some method to do the Queued image download in background thread with the signature void LoadImages(int startIndex, int count)
In the code snippet you can also see the place where we can detect the scroll end. That is very useful for pagination scenarios to download the next set of data from the service.
             image

Please take a look at the source code, that shows the image download in a background thread and the visible range of visuals getting downloaded when we stop scrolling.

Have fun with Wp7 development!

Monday, March 21, 2011

WP7Dev Tip 1– Optimizing the app by reusing already created visuals

Developing a good application in the phone need not be accompanied with so much of hacking around or doing lot of non-conventional tricks. Most of the time those tricks make us deviate from the regular ways of development, make the code ugly and unmaintainable.  If we can get a sense of the pain-points and limitations of the platform early, then find a way around it and separate those concerns out of your business logic so as to proceed with a smooth development. I am explaining a pretty basic yet useful idea of how to reuse the complex visuals you have already created in previous pages of the application at runtime. Please note that this may not be applicable to small applications involving two or three pages of total navigation.
Problem : Imagine you have an application which needs to navigate to the same view over and over again. For example the Movie details page of IMDb or Netflix app, or profile page of Facebook or Twitter, those pages get called many times in the life span of an application instance. If we approach it in a standard way of putting a Panorama/Pivot inside a PhoneApplicationPage say MovieDetails.xaml, then each time we go to that page, creates a new instance of the page. Also it creates totally new Pano/Pivot in the visual tree under that page and when you navigate away, that gets pushed to the navigation stack. Suppose this pano when it gets rendered takes up 20MB( IMDb app got more good resolution images in a pano and one MovieDetails took around 20MB to render), so when we navigate to 5 different movies the app holds up a 100MB memory footprint. Since Garbage collection is a lazy operation, that memory wont get easily released. And as you know the platform will kill the app because it reached an unacceptable memory level.
Solution : So now we are clear on one thing, we don’t need to recreate that pano over and over. Because when the first movie details showed up the system did a hard job of creating all those visuals in memory. So it is a matter or showing that pano visual again with a totally different Movie as its new DataContext.
Technical Solution : It is pretty easy to solve this by treating the PhoneApplicationPage as merely a Content placeholder. We can do it in many ways, in my design I have kept only one xaml phonepage and put a special Layout panel (say Grid) in it. And depending on the ViewModel type to be displayed we can always instantiate a DataTemplate(the Pano will be a MovieDetailsDataTemplate in this case) and add that UIElement in to the layout. This operation can be at the PhoneApplicationPage.NavigatedTo() override. Now when this page is navigated away (NavigatedFrom()) we can easily remove that particular UIElement from the layout/page and keep it in the memory. So the next time when it demands a similar view, it will just get loaded back from the memory on to another page instance. This way, all the page instances going to the navigation stack would be pretty much a ‘dummy’ container and wouldn’t hold up any memory at all.
Result : With out this approach we could go only 5 or 6 ‘Movie –> Actor –> Movie’ loops, now we can do 100s of page navigations on that movie-actor loop ( Check out the IMDb app)
And there are many other advantages of keeping a single PhoneapplicationPage class for the entire app, I will be explaining it in my next blog

Wednesday, September 15, 2010

An easy Windows Phone 7 Photo Viewer using Pivot control #WP7 Tip

Technorati Tags: ,,,

photoviewer  Source Code

Here is a small trick using the Pivot control for a Photo viewing experience. Imagine a Pivot control with out any header and the image as Pivot items. Yes it is that easy :). Since the Pivot supports for the Phone orientation you can enjoy the picture viewing both in Portrait and Landscape. I am giving step by step info if you are totally new to WP7 and XAML styling.

And please note that the performance wont be that great if you have many images in the Pivot control. So you may need to do design that around or use some tricks to clean up the memory well.

1) Place a Pivot control and override the Style. What we wanted is to take out all the Header Templates and other extra puddings.

        <Style x:Key="emptyPivot" TargetType="controls:Pivot">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="controls:Pivot">
                        <Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
                            <ItemsPresenter x:Name="PivotItemPresenter" Margin="{TemplateBinding Padding}" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

2) Override the ItemContainerStyle and place Image control for displaying Photo.

      <Style x:Key="PhotoVieweritemStyle" TargetType="controls:PivotItem">           
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="controls:PivotItem">
                     <Image Source="{Binding}"/>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>

3) Add ItemsSource Binding to the Pivot control with your Photo Collection.

        <controls:Pivot
             ItemsSource="{Binding YourImageCollection}"
             Style="{StaticResource emptyPivot}"
             ItemContainerStyle="{StaticResource PhotoVieweritemStyle}" />    

 

Happy WP7 Coding!!!

Thursday, March 11, 2010

UniformGrid for Silverlight

My recent Silverlight project had a need to distribute the items in rows and columns. I had to dynamically calculate the number of columns and rows it needed based on some logic. So it was clear that I need UniformGrid as in WPF so that I can bind my ViewModel properties to Rows and Columns properties of the Panel. But it was a bit surprising to me that there isn’t a Silverlight UniformGrid either in Silverlight SDK or in Silverlight ToolKit. So here is one I ported from WPF. Check out the Silverlight 3.0 demo below.
Get Microsoft Silverlight
You can also download the sample project

Thursday, March 04, 2010

A Simple Accordion banner using ListBox

Get Microsoft Silverlight

This sample is to show how easily we can create an Image-accordion entirely in Expression Blend. This is utilizing the ListBox’s Selected and UnSelected VisualStates. Place a ListBox and override its ItemContainerStyle then adjust the width on the Selected and UnSelected visual states. When we override the ItemsPanel we can make it orientation to Horizontal on the StackPanel. Pretty easy and there is no C# needed. Paste the below XAML in your user control

<UserControl.Resources>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
<Style x:Key="ListBoxItemStyle1" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid x:Name="grid" Background="{TemplateBinding Background}" Width="55">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected">
<Storyboard>
<DoubleAnimation Duration="0:0:0.3" To="55" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid" >
<DoubleAnimation.EasingFunction>
<ElasticEase EasingMode="EaseIn" Springiness="6" Oscillations="0"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<DoubleAnimation Duration="0:0:0.3" To="500" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="grid" >
<DoubleAnimation.EasingFunction>
<ElasticEase EasingMode="EaseIn" Springiness="6" Oscillations="0" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}"/>
<Rectangle x:Name="FocusVisualElement" RadiusY="1" RadiusX="1" Stroke="#FF6DBDD1" StrokeThickness="1" Visibility="Collapsed"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>

<Grid x:Name="LayoutRoot" Background="#FFAFAFAF" Margin="10">
<ListBox SelectedIndex="0" ItemsPanel="{StaticResource ItemsPanelTemplate1}" ItemContainerStyle="{StaticResource ListBoxItemStyle1}" BorderBrush="{x:Null}" Background="{x:Null}" VerticalAlignment="Center" HorizontalAlignment="Center" Height="285" Margin="10">
<Image Source="B.JPG" Stretch="UniformToFill" Margin="0,0,1,0"/>
<Image Source="A.JPG" Stretch="UniformToFill" Margin="0,0,1,0"/>
<Image Source="C.JPG" Stretch="UniformToFill" Margin="0,0,1,0"/>
<Image Source="D.JPG" Stretch="UniformToFill" Margin="0,0,1,0"/>
<Image Source="E.JPG" Stretch="UniformToFill" Margin="0,0,1,0"/>
</ListBox>
</Grid>

Button Style - Silverlight

Really surprised to see from the google analytics that one of my old post regarding WPF control template still has many viewers . So I just thought of creating a Silverlight version of the same. All the buttons are from the same style with different Button.Background, the elliptical one has less height and more width on it.

If you want to check out the XAML, please download from here

Tuesday, August 04, 2009

Silverlight 3 Multi-Touch with Windows 7 and HP Touch Smart.

Inspired by the blog Silverlight 3 Multi-touch: The Basics by Tim Heuer, I thought of experimenting with it and creating a small sample. The logic is pretty simple, I have used TranslateTranform and ScaleTranform to do the movement and scaling respectively. When the TouchAction is Move we can distinguish whether it is a single touch or multi touch from the TouchPointCollection count. When it is a double touch you can calculate the change of distance between the two touch points and transform that as ScaleTransform of the Visual. Please watch the video, I shot on my office HP Touch smart machine.

Have you got a multi-touch monitor?, then run the application here and feel the Silverlight touch. You can set your browser in Full-Screen mode to get a good experience. Please note that the current Silverlight version doesn't accept Touch inputs while running in Silverlight full screen mode(ie, App.Current.Host.Content.IsFullScreen =true). You can read more on Silverlight multi touch on MSDN

Click here to run the application

image

Thursday, July 30, 2009

Slider Preview as Expression Blend 3 Behavior

Behaviors is one of the new features Expression blend 3 has introduced to make interactivity easy. Behavior allows us to wrap the interaction logic as a very discrete unit and attach to any UI elements. My previous blog post about Attaching preview behavior to a Slider control, is a good scenario to make as a Behavior. I have used Attached Dependency property as a technique to make it happen in the earlier post, though the concept is almost same but Blend Behavior gives a neat and clean abstraction. It also allows a Blend user to just drag-drop to any Slider control. So this is a great functionality which helps boost the re-usability in a cool way.

Problem : Create a behavior to display the value of a Slider control when hover over.

First step is to make a class which derived from Behavior class. public class PreviewSliderBehaviour : Behavior<Slider> Here I am explicitly giving Slider class as my targeted UI Element type since this behavior is meaningless to other elements. Now we need to override two methods of Behavior class, protected override void OnAttached() and protected override void OnDetaching() . I can subscribe mouse events in the OnAttached() method and unsubscribe the same in the OnDetaching() method.

     protected override void OnAttached()
{
m_attachedObject = AssociatedObject;
// Gives you the instance of the Slider you attached this behavior on to

if (m_attachedObject != null)
{
m_attachedObject.PreviewMouseMove +=
new System.Windows.Input.MouseEventHandler(item_PreviewMouseMove);
m_attachedObject.MouseLeave +=
new System.Windows.Input.MouseEventHandler(item_MouseLeave);
}
base.OnAttached();
}
/// Called when the behavior is removed from the DependencyObject
protected override void OnDetaching()
{
if (m_attachedObject != null)
{
m_attachedObject.PreviewMouseMove -=
new System.Windows.Input.MouseEventHandler(item_PreviewMouseMove);
m_attachedObject.MouseLeave -=
new System.Windows.Input.MouseEventHandler(item_MouseLeave);
}
base.OnDetaching();
}

The important logic lies in the MouseMove handler, it creates a ContentAdorner(a custom adorner, you can see in the source code) and sets the value calculated here to the ContentAdorner.Content property. This also sets the ContentAdorner’s placement point to the mouse point so that the adorner moves along with the mouse move.

     void item_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
Slider slider = sender
as Slider;
if (popup == null)
{
//Creates a new ContentAdorner with the given Style, Content Style is a Dependancy property of this behaviour
popup =
new ContentAdorner(slider, ContentStyle);
AdornerLayer layer = AdornerLayer.GetAdornerLayer(slider);
layer.Add(popup);
}
popup.Visibility = Visibility.Visible;
//Finding out the PART_Track from the controltemplate of the Slider
Track _track = slider.Template.FindName(
"PART_Track", slider) as Track;
//Calculates the mouse position
Point position = e.MouseDevice.GetPosition(_track);
//This method gives the exact preview value of the Slider
double value = _track.ValueFromPoint(position);
if (slider.SmallChange != 0.0)
{
double diff = value % slider.SmallChange;
value -= diff;
}
//Setting the value as the content of the ContentAdorner
popup.Content = Math.Max(slider.Minimum, Math.Min(slider.Maximum,
value));
position = e.GetPosition(slider);
position.Y = slider.ActualHeight / 2.0;
popup.PlacementOffset = position;
}

Now it is pretty easy to add this behavior to any Slider control, if you are in Expression Blend just opens the behavior tab and drag and drop this on to any Slider in the designer area. The XAML code will looks like,

<Slider x:Name="sld" Minimum="00" Maximum="100"    SmallChange="0.5" IsSnapToTickEnabled="True" TickFrequency="0.5">
<i:Interaction.Behaviors>
<local:PreviewSliderBehaviour ContentStyle=
"{StaticResource PreviewStyle}"/>
</i:Interaction.Behaviors>

</Slider>

Source Code

Few other links you may be interested to read about Behaviors

Gallery of Behaviors

AN INTRODUCTION TO BEHAVIORS, TRIGGERS, AND ACTIONS

Using a Behavior to magnify your WPF applications