Showing posts with label sdk. Show all posts
Showing posts with label sdk. Show all posts

Wednesday, 15 May 2013

Why setting a control Height and Width to 0 is not the brightest idea inside a Windows Phone project

I am doing this small post because I have battled the whole morning with this bug and finally got it and it might save you some time if you read it and have the same problem. 

Scenario: Pivot with two items and at some point the swipe on one of the items doesn't work anymore. Putting a button on the PivotItem that doesn't swipe I can still change the selected item and the second item still swipes correctly.

Cause: I was setting the Height=0 and Width=0 on a control inside the PivotItem (in my project I don't want my control to be collapsed). The problem presents itself if you set any of the controls inside a PivotItem to Height and Width = 0 when the PivotItem is selected. If on the other hand you set the Height and the Width to anything >1 the PivotItem continues to swipe correctly. Even more strange: if the PivotItem is not selected when  you set the Width and Height to 0 and swipe to the control's PivotItem everything will still work correctly. So pay attention better not use set Width and Height =0 on UI controls. 

If you want to test it yourself and maybe tell me what really happens I am attaching a small project created from a Windows Phone Pivot application where I've added a menu that will set the Height and Width of the list inside the first PivotItem to 0. I also set the background of the first PivotItem to green so you will see that it is still expanded. 



How to reproduce the problem: If you execute the menu command with the first PivotItem selected you will see that the pivot doesn't swipe anymore. If you change the values to 1, run the app again and execute the menu with the first PivotItem selected you will see that the pivot still swipes correctly. If, on the other hand, you let the values set to 0 but when executing the menu you have the second PivotItem selected you will see that the first item stil swipes correctly. Bug? Feature? Just pay attention to setting controls to Width and Height 0 because you might have problems with the UI and you won't know what is causing it.


NAMASTE









Monday, 13 May 2013

Fix Panorama layout when upgrading your project to OS 8.0 SDK

  This will be a really short blog post but might save you some time if you have an OS 7.1 Panorama project and decide to upgrade the project to 8.0 SDK. After the upgrade you might see that the layout of your old page changed and you have less content available for the items and also the header looks different. Don't try to fix the problem by changing the margin of the control on the OS 8.0 SDK. The reason why this happens is because the Windows Phone SDK team decided to "tweak" a little bit the default style for the Panorama control, to be more precise the TitleLayer part of the style.
  On Windows Phone OS 7.1 projects the TitleLayer looks like this:

 <controlsPrimitives:PanningTitleLayer x:Name="TitleLayer" CacheMode="BitmapCache" ContentTemplate="{TemplateBinding TitleTemplate}" Content="{TemplateBinding Title}" FontSize="187" FontFamily="{StaticResource PhoneFontFamilyLight}" HorizontalAlignment="Left" Margin="10,-76,0,9" Grid.Row="0"/>  

while on OS 8.0 we have:

 <Primitives:PanningTitleLayer x:Name="TitleLayer" CharacterSpacing="-35" ContentTemplate="{TemplateBinding TitleTemplate}" Content="{TemplateBinding Title}" FontSize="170" FontFamily="{StaticResource PhoneFontFamilyLight}" HorizontalAlignment="Left" Margin="10,-34,0,0" Grid.Row="0"/>  


You can see that not only the margin have changed (the reason why on OS 8.0 version we have less space in the content -44px ), but also the font size changed from 187 to 170 producing these visual differences:


The solution to this problem is pretty simple: extract the old style of the Panorama control (the easiest way is using Blend) and apply to both WP7.1 and OS 8.0 versions of your project. This way the UI will be consistent between the two versions of the app. If you don't want to use Blend I am attaching the default OS 7.1 style so you can directly copy/paste it in your project and apply it to your Panorama control.

 <Style x:Key="PanoramaStyleWP71" TargetType="controls:Panorama">  
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<controlsPrimitives:PanoramaPanel x:Name="panel"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:Panorama">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<controlsPrimitives:PanningBackgroundLayer x:Name="BackgroundLayer" HorizontalAlignment="Left" Grid.RowSpan="2">
<Border x:Name="background" Background="{TemplateBinding Background}" CacheMode="BitmapCache"/>
</controlsPrimitives:PanningBackgroundLayer>
<controlsPrimitives:PanningTitleLayer x:Name="TitleLayer" CacheMode="BitmapCache" ContentTemplate="{TemplateBinding TitleTemplate}" Content="{TemplateBinding Title}" FontSize="187" FontFamily="{StaticResource PhoneFontFamilyLight}" HorizontalAlignment="Left" Margin="10,-76,0,9" Grid.Row="0"/>
<controlsPrimitives:PanningLayer x:Name="ItemsLayer" HorizontalAlignment="Left" Grid.Row="1">
<ItemsPresenter x:Name="items"/>
</controlsPrimitives:PanningLayer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


NAMASTE

Thursday, 9 May 2013

Type forwarding and XAML sharing between WP OS 7.1 and 8.0 projects

    This post is about a new feature available in Windows Phone OS 8.0 SDK called Type Forwarding.

    Have you ever wondered how does the Windows Phone 8.0 SDK handles the fact that the Panorama, Pivot controls changed the namespace and the assembly from OS 7.1 SDK to OS 8.0 SDK? (80% that you haven't :) ). I recently had to migrate an OS 7.1 project to OS 8.0, but also keep the old one (duplicated the old project and upgrade the duplicated one).

    Here is the story of what happens when you upgrade an OS 7.1 project that uses Panaroma or Pivot to OS 8.0:
    If you start a new Windows Phone Pivot App with the target OS 8.0 inside MainPage.xaml the prefix "phone" is used for the Pivot control where "phone" is:

 xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"  

    If, on the other hand, you create a new Windows Phone Pivot App with the target OS 7.1 inside MainPage.xaml the prefix "controls" is used for the Pivot/Panorama control where "controls" is:

 xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"  

    The real "magic" happens when you upgrade the Windows Phone 7.1 project to OS 8.0. The MainPage.xaml page doesn't change (you will still see the "controls" tag is kept in order to be able to better share the code between the versions), but instead a reference to Microsoft.Phone.Controls.dll is added to the OS 8.0 reference that is not used if you create a new project with target OS 8.0. If you wonder if by adding this reference you use the old version of the controls the answer is NO. What this assembly does is that is uses a really neat and new  feature of the .Net compiler called Type Forwarding. This feature can be used when you move a class from one namespace/dll (assembly) to another and you don't want to recompile the application to reference the new dll but you will only deploy the two dlls where the first one (the one that the application already knew uses the Type Forwarding to tell the application that a certain class/es moved to another assembly). In the case of Windows Phone OS 8.0 SDK the usage is even "cooler" as it enables you to use the same XAML for both OS 7.1 projects and OS 8.0 ones. Inside AssemblyInfo.cs of Microsoft.Phone.Controls.dll OS 8.0 version we have all the declarations needed to forward the types to their new locations:

 [assembly: TypeForwardedTo(typeof(Panorama))]  
[assembly: TypeForwardedTo(typeof(PanoramaItem))]
[assembly: TypeForwardedTo(typeof(Pivot))]
[assembly: TypeForwardedTo(typeof(PivotItem))]
[assembly: TypeForwardedTo(typeof(PivotItemEventArgs))]
[assembly: TypeForwardedTo(typeof(AnimationDirection))]
[assembly: TypeForwardedTo(typeof(PanningBackgroundLayer))]
[assembly: TypeForwardedTo(typeof(PanningLayer))]
[assembly: TypeForwardedTo(typeof(PanningTitleLayer))]
[assembly: TypeForwardedTo(typeof(PanoramaPanel))]
[assembly: TypeForwardedTo(typeof(PivotHeaderItem))]
[assembly: TypeForwardedTo(typeof(PivotHeadersControl))]

I am attaching a small project called TypeForwarding that implements the same functionality as Microsoft.Phone.Controls.dll OS 8.0 version.

Other usages that I can thing of:

  • Flurry SDK changes the name of the namespace for the Api class for WP7SDK to WP8SDK (bad choice when you need code sharing). If you want to keep the same code for the OS 7.1 and the OS 8.0 version of the app you will have to use conditional compiling for every file where you use the Api class. Much easier would be to create an OS 8.0 library project with the default namespace WP7SDK and forward the Api class to the WP8SDK added as a reference to the library project. This way the old WP7SDK will continue to work as it was on the OS 8.0 using the OS 8.0 version of the Flurry SDK.
  • MVVM Light. If you use inside your XAML the EventToCommand this is not xaml shareable between OS 7.1 and OS 8.0 because the assemblies changes from GalaSoft.MvvmLight.Extras.WP71.dll to GalaSoft.MvvmLight.Extras.WP8.dll. The easiest approach in this case (an open source) would be to recompile the dll and use the same name for both versions of the dll. But if you don't have access to the source code of the dll you could use type forwarding.  Also a third approach would be to derive your on class like MyEventToCommand and use this inside the xaml.
Keep in mind this neat feature because you might need it. I would also love to see, in the next version of the SDK, the possibility to use MarkupExtension this way we could conditionally compile parts of the XAML depending on the version of the SDK the app is running on. Have a look at this blog post that explains how it works on WPF projects.



Till next post NAMASTE and have fun coding for Windows Phone!

Wednesday, 24 April 2013

Detect the screen resolution for Windows Phone OS 7.1 applications

    As you probably know Windows Phone 7.1 applications run perfectly on Windows Phone 8 devices. This means that your application/s could run on multiple display resolutions (which are the resolutions supported by Windows Phone 8 devices). If you want to take advantage of the new resolutions (for example downloading higher quality images for higher resolutions devices, fix some minor UI anomalies on higher resolutions) you will need to know the ScaleFactor of the device. The property is only available in the Windows Phone 8.0 SDK, but the good news is that you can access it using reflection.

Solution:
We retrieve the Get method of the ScaleFactor property and invoke it only if the application is running on an Windows Phone 8 device.

Here is the source code:
  public static Size DisplayResolution  
{
get
{
if (Environment.OSVersion.Version.Major<8)
return new Size(480,800);
int scaleFactor=(int) GetProperty(Application.Current.Host.Content, "ScaleFactor");
switch (scaleFactor)
{
case 100:
return new Size(480, 800);
case 150:
return new Size(720, 1280);
case 160:
return new Size(768, 1280);
}
return new Size(480, 800);
}
}
private static object GetProperty(object instance, string name)
{
var getMethod= instance.GetType().GetProperty(name).GetGetMethod();
return getMethod.Invoke(instance, null);
}

I am also attaching a small sample Windows Phone OS 7.1 test project.


SOURCE CODE

P.S. I think Telerik could use this method to fix this RadToolTip visual anomaly (the 1 pixel width lines that I have filled with blue for contrast) :


NAMASTE

Tuesday, 2 April 2013

Smooth scrolling content on Windows Phone

     Gotta say that I am not 100% satisfied about the title of this blog post, but since I haven't found a better one I will use this one (don't get it wrong windows phone has smooth scrolling implemented). This post is focusing on how to smooth scroll the content of a ScrollViewer. If you are using the ScrollViewer you know that it already has the method ScrollToVerticalOffset that can be used to manually scroll the content but this method doesn't have any animation implemented so you will see only a fast redraw of the new content without getting the "feeling" that the content scrolled to the new position. The easiest way to achieve this task would be using a StoryBoard with an Animation on the property VerticalOffset of the ScrollViewer, but VerticalOffset is a read-only property so it cannot be set and therefore cannot be used for animation.
     The solution I found was to build a custom control and add a custom property that can be used as a target for a DoubleAnimation. The attached sample (see the link at the end of the post) is using a ListBox as the content of my Custom Control but you can use anything else inside the control (a better approach for the ListBox would be to create a custom control derived directly from ListBox and use the built-in ScrollViewer). 
      Let's start from the XAML part of the User Control:

  <ScrollViewer x:Name="scroller">  
<ContentPresenter Content="{Binding ContentArea, ElementName=userControl}"/>
</ScrollViewer>

    So we have a ScrollViewer which inside has a ContentPreseter that has its content binded to the control's property ContentArea. Now let us have a look at the .cs code.

 public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register("VerticalOffset",  
typeof(double), typeof(SmoothScroller), new PropertyMetadata(VerticalOffsetPropertyChanged));
public double VerticalOffset
{
get { return (double)this.GetValue(VerticalOffsetProperty); }
set { this.SetValue(VerticalOffsetProperty, value); }
}
private static void VerticalOffsetPropertyChanged(object sender, DependencyPropertyChangedEventArgs args)
{
SmoothScroller cThis = sender as SmoothScroller;
cThis.scroller.ScrollToVerticalOffset((double)args.NewValue);
}
public static readonly DependencyProperty ContentAreaProperty = DependencyProperty.Register("ContentArea", typeof(object), typeof(SmoothScroller), null);
public object ContentArea
{
get { return (object)GetValue(ContentAreaProperty); }
set { SetValue(ContentAreaProperty, value); }
}

     The property that we will use for animation is the VerticalOffset that uses the method VerticalOffsetPropertyChanged to scroll to a vertical offset inside the control's scroller. The property VerticalOffset can be animated and we will use it to smooth scroll the ListBox content.
     Here is the content of the MainPage.xaml

  <uc:SmoothScroller x:Name="smoothScroller">  
<uc:SmoothScroller.ContentArea>
<ListBox x:Name="lstItems" ItemsSource="{Binding Items}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource DataTemplate}" >
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</uc:SmoothScroller.ContentArea>
</uc:SmoothScroller>

     So we have the SmoothScroller control which inside its ContentArea has a ListBox (the ListBox has it's scrollviewer disabled). What the sample does is it is changing the selected item every second (incrementing the selectedindex) and scrolls the content so that the newly SelectedItem is centered in the ScrollViewer. Here is the code used for scrolling:

  void dt_Tick(object sender, EventArgs e)  
{
((ListBox)smoothScroller.ContentArea).SelectedIndex = idx;
var container = ((ListBox)smoothScroller.ContentArea).ItemContainerGenerator.ContainerFromIndex(idx) as FrameworkElement;
var transform = container.TransformToVisual(smoothScroller.scroller);
var elementLocation = transform.Transform(new Point(0, 0));
double newVerticalOffset = elementLocation.Y + smoothScroller.scroller.VerticalOffset - smoothScroller.scroller.ActualHeight / 2 ;
//Animate transition
DoubleAnimation verticalAnimation = new DoubleAnimation();
verticalAnimation.From = smoothScroller.scroller.VerticalOffset;
verticalAnimation.To = newVerticalOffset;
verticalAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(500));
var sb = new Storyboard();
sb.Children.Add(verticalAnimation);
Storyboard.SetTarget(verticalAnimation, smoothScroller);
Storyboard.SetTargetProperty(verticalAnimation, new PropertyPath(SmoothScroller.VerticalOffsetProperty));
sb.Begin();
idx++;
if (idx >= 56)
dt.Stop();
}

     Pretty basic: select the new index in the ListBox, calculate the new VerticalOffset so that the newly selected item is centered in our scrollviewer and create and start a 500ms animation for the SmoothScroller.VerticalOffsetProperty. Anyway I am sure that you will better understand how it works when you will try the sample code.
     The sample is far from perfect (before starting a new animation I should check if the old one finished, should not automatically scroll when the user is manipulating the list,...).
     Here is a screenshot from the sample:

As usual let me know if you need help. The code works on both Windows Phone 7.1 and Windows Phone 8 SDK.

SOURCE CODE


Monday, 18 March 2013

How to debug Windows Phone HTML5 Apps

  Debugging HTML applications is never an easy task and until today I did not know how to approach this for Windows Phone HTML5. The technique I will describe in this post can be applied also for Windows Phone 7.1 applications using Phonegap or Android/iOS applications.
   The "secret" tool for debugging the html content inside our applications is called WEINRE which comes from WEb INspector REmote. Weinre is a debugger for web pages, like FireBug (for FireFox) and Web Inspector (for WebKit-based browsers), except it's designed to work remotely, and in particular, to allow you debug web pages on a mobile device such as a phone. 
    In order to install Winre you will need to download and install NodeJS


    Once you have installed NodeJS restart your machine this way you will be able to run the NodeJS commands from the command prompt. After restart open a command prompt window and run this command:
 npm install weinre -g  
This will install the Weinre package globally. This is what you should see in the Command Prompt window:


    When the installer has finished its work you are ready to run the Weinre server on your PC. Execute this command from the Command Prompt:
 weinre --boundHost -all- --debug -true  
    With these parameters Weinre should also open the firewall port. For more parameters have a look at this page. You can verify if the server started by opening a browser page and loading 127.0.01:8080 (8080 is the default port for Weinre). If you are seeing this page then the server is running:


   Now click on the Debug Client User Interface link where you will be able to see if any client is connected and debug the connected clients.
    Let's create the Windows Phone HTML5 application. Use the SDK template to create a new project, open the page index.html inside the folder Html and add this line to the head section:
 <script src="http://[the server ip]:8080/target/target-script-min.js#anonymous"></script>  
replace [the server ip] with the IP of the PC running the Winre server and run the application. If everything went as we expected in the Debug Client user Interface on the Server we should see one Target connected:
    Once the target Windows Phone page is connected you can inspect and change the DOM in real-time, execute javascripts:

 
 
    In this particular case I've only changed the background of the page but you can do whatever you want. Here you can find further details on how to use the Server User Interface.
    Using the Console panel you can execute arbitrary JavaScript expressions/statements. It also shows the output from various console methods, like console.log().

 

    This is pretty much everything. Simple and veryyyyyy useful if you need to debug your HTML5 windows phone applications.
    As usual don't hesitate to contact me if you have further questions.

NAMASTE

Tuesday, 4 September 2012

What MediaLibrary needs/is missing (Windows Phone)


      As we (average developers :) ) still don’t have access to the Windows Phone 8 SDK I decided to write a post on the current MediaLibrary limitations for Windows Phone. I only hope that someone from the team will read this post and maybe there is still time to improve some aspects in the new version. Everything here is my personal  opinion.

So what is missing from the MediaLibrary?

1.     The Token property exposed on the Picture object

The most important for me. Why? Let’s open Internet Explorer on the emulator and go on a webpage that has a picture in it, tap-n-hold and save it twice. If we use Windows Phone commands to launch the Pictures hub in the emulator and go to the Saved pictures album we will see both pictures (same picture but different items). Now let’s create a new project and see what we can get using the MediaLibrary class. I will use this simple code to debug and stop on the pictures to watch its properties:

MediaLibrary ml = new MediaLibrary();
//MediaPlayer.Queue.ToString(); ;
varalbums = ml.RootPictureAlbum.Albums;
foreach(var album in albums)
if (album.Pictures.Count>0)
foreach(Picture pct in album.Pictures)
{
boolstophere = true;
}


  
We can see both pictures but the BIG problem is that the only way to differentiate between the two of them is the Date property (not very elegant, Handle is not public property). The Token property  makes a lot of sense to tell which picture is which (maybe also a Path member could be added but Token is way better as we already have the method to open a picture from its Token and you won't have to iterate all the MediaLibrary just to get the picture we want).

This property should be fairly easy to add as it already exists internally (when we use the PhotoChooser we will get the token associated with the selected picture and we will be able to open the picture) . 

The token could be extended also to the PictureAlbum class. It doesn’t make much sense to iterate the MediaLibrary to find a specific album if I already know what PictureAlbum I want.

2.     The possibility to create new picture albums

In this moment the Pictures Hub already has built-in albums but it is not possible to create new albums directly from the phone. It is possible to do it from Zune (which will not be used anymore) but it is not a trivial task (at least till you understand how it works). So we are mainly stuck with two “containers”: Camera Roll and Saved Pictures which is not enough for a device that theoretically could hold up more than 1GB of photos. From here the need to have tools to organize your photos better by creating new albums and copying/moving photos between albums. Maybe it is a little late to implement it in the "standard" WP8 UI as we are two months away from the official launch of the first phones on the market but maybe not too late to add the functionality in the development tools so the developers can implement it in their apps. This way a photo app could create its album and then the users will know in which album to look when they want to find pictures modified/created by a certain app.

3.     Access to the videos on the device

Needed since the first version of windows phone but still no sign of it. Videos are an important part of the device media and developers need access to this part of the MediaLibrary to enable applications like video processing, video backup, video creation and more.

4.     Make the Favorites Pictures album work

This functionality already exists in the Windows Phone Mango/Tango but it doesn’t work in the current version of the SDK. I’ve already posted a question on the forum with no answer till now. The count of the Favorites album is always 0.


5.     Enable MediaLibrary access in the background task

Useful for applications that want to backup the pictures from the device automatically. If it’s a problem of security see 6 but if the user already agreed at some point (capabilities, ask permission) it doesn’t make sense to lock the access to the medialibrary from the background tasks.

6.    Security/capabilities

I think the current ID_CAP_MEDIALIB  is too generic. It would be better to have specific CAP for pictures, videos and songs. They are pretty distinctive and a photo editor wouldn't need access to the songs on the device? Also the user should be warned that his photos might contain GPS data in the EXIF header and he should agree to let the application access those informations.

P.S. Almost all of the features requested are already implemented in the iOS development tools.

NAMASTE