Tuesday, May 11, 2010

Another Strange Silverlight Error: “Layout cycle detected. Layout could not complete”

Wow! Is this one ever frustrating! So here’s the situation:

I’ve got a datagrid which uses RowGroups. Everything is working just fine until I get a request from the product owner to hide/show several of the columns on that datagrid by clicking a button. I figured “This isn’t going to be too bad. I’ve done this before with other datagrids. Great, I’ll have it done in 10 minutes.” WRONG! To my surprise, I wrote some code very similar to what I’ve done in the past, but I started seeing this funky error “Layout cycle detected. Layout could not complete”. Because this is a Silverlight error, I did not get any other helpful information. Thanks so much Silverlight. Well, I can’t tell you that I completely understand the internals of Silverlight and what is causing this issue, but I do know that it has something to do with looping inside the the UpdateLayout method is executing for the datagrid. It seems to be getting stuck in an infinite loop. After a lot of searching and trying out different things, I came up with a workaround. If you are experiencing this problem, try removing the datagrid from its parent prior to making the change (in my case adding/removing columns) and then add the datagrid back to it’s parent’s Children collection immediately after you make the change.

This solved it for me. Here is a snippet:

            if (show == true)
{
_clmOne.Visibility = Visibility.Visible;
_clmTwo.Visibility = Visibility.Visible;
_clmThree.Visibility = Visibility.Visible;
}
else
{
//Hack:Need to remove the grid prior to adding columns to avoid Exception.
this.LayoutRoot.Children.Remove(myDataGrid);
_clmOne.Visibility = Visibility.Collapsed;
_clmTwo.Visibility = Visibility.Collapsed;
_clmThree.Visibility = Visibility.Collapsed;
this.LayoutRoot.Children.Add(myDataGrid);
}


I hope this helps you guys out. Happy Silverlighting!


Wednesday, April 28, 2010

Are You Annoyed With The Visual Studio XAML Design View?

I know I was! Sure, Visual Studio 2010 has a much improved designer (especially if you are working with Silverlight), but for the most part, the designer for Silverlight and WPF applications is pretty weak. I would much rather work in Blend or straight XAML. If I had to edit a XAML page in Visual Studio, I would always open the file and immediately switch to full XAML view. The designer always took too long to load and it wasted a lot of my time. Well, if you are in the same boat, here is a little tip. You can configure Visual Studio to always open XAML files in full XAML view and bypass the designer. To do this, go to the Tools menu and select Options. In the options dialog, select the Text Editor element on the left hand side and go to XAML and the Miscellaneous. Under the Default View section, make sure the ‘Always open documents in Full XAML view’ is checked and click ok. That should do it. From now on you will open your XAML files directly in the XAML view and you won’t have to wait for the editor to load and tell you it can’t render the XAML.

image

Note: The version of VS I am running is VS 2010 Ultimate.

Thursday, April 15, 2010

Silverlight 4 Just Released – Books to Help You Out

 

With the release of Sivlerlight 4 and all the tools related to that technology, now is a great time to learn how to develop rich web applications using Microsoft Silverlight. This knowledge will also allow you to create rich applications for the upcoming Windows Phone 7 devices. Follow the links below to purchase some of the newest (most up to date) books on Silverlight development.

  

 

Friday, March 26, 2010

How to use Isolated Storage on Windows Phone 7

 

image

I wrote a little sample application that lets the user work with the isolated storage on a Windows Phone 7 device. I won’t bother you with the details of the xaml because the UI is relatively straight forward. There are only a handful of controls and they are all pretty standard. What I want to share here is the code behind that makes this application work. Besides, it’s not really the most amazing app out there, it’s just meant to show you how to work with ISO storage.

The key take-aways from this are:

1) You will need to add reference to the System.IO.IsolatedStorage assembly and add the corresponding using statement.

2) You save and retrieve the settings by calling IsolatedStorageSettings.ApplicationSettings

3) You access the setting values via their keys - IsolatedStorageSettings.ApplicationSettings[“key”]= “value”;

Hopefully this gets you started saving and retrieving data to and from a Windows Phone 7 device.

More to come… happy coding!

 

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 Microsoft.Phone.Controls;
using System.IO.IsolatedStorage;
using System.IO;

namespace Isolated_Storage
{
public partial class MainPage : PhoneApplicationPage
{
private IsolatedStorageSettings appSettings;

public MainPage()
{
InitializeComponent();

SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;

btnAdd.Click += new RoutedEventHandler(btnAdd_Click);
btnRead.Click += new RoutedEventHandler(btnRead_Click);
txtValue.TextChanged += new TextChangedEventHandler(txtValue_TextChanged);

appSettings = IsolatedStorageSettings.ApplicationSettings;

UpdateSettingsCount();
}

private void UpdateSettingsCount()
{
lblCount.Text = String.Format("App Settings Count: {0}", appSettings.Count);
}

void txtValue_TextChanged(object sender, TextChangedEventArgs e)
{
btnAdd.IsEnabled = txtValue.Text.Trim().Length > 0;
}

void btnRead_Click(object sender, RoutedEventArgs e)
{
lstItems.Items.Clear();
LoadData();
}

void btnAdd_Click(object sender, RoutedEventArgs e)
{
IsolatedStorageSettings.ApplicationSettings[(appSettings.Count + 1).ToString()] = txtValue.Text;
UpdateSettingsCount();
}

private void LoadData()
{
for (int i = 0; i < appSettings.Count; i++)
{
string entry = string.Format("Key: {0} {1}Value: {2}", i + 1, Environment.NewLine, appSettings[(i + 1).ToString()].ToString());
lstItems.Items.Add(entry);
}
}
}
}



Thursday, March 25, 2010

How to add an Application Bar to your Windows Phone 7 App

When developing Windows Phone 7 apps, it is recommended not to include custom menus within the application in order to keep apps consistent across the platform. Instead developers should use the Application Bar to place such menu-like commands.

To do this, you first add a reference to the Microsoft.Phone.Shell assembly. You then need to add your images (button icons) to the project. You need to change the Build Action to Content and set Copy to Output Directory to Copy Always.

image

Here are the best practices Microsoft recommends for the images used in the Application Bar (ooops… I’m not following all of these in my example)

  • Icon images should use a white foreground on a transparent background using an alpha channel. The Application Bar will colorize the icon according to the current style settings and colored icons can cause this effect to display unpredictably.
  • The circle displayed on each Icon Button is drawn by the Application Bar and should not be included in the source image.
  • Icon images should be 48 x 48 pixels in size. The white foreground graphic for the button should fit in a 26 x 26 area square in the center of the image so that it does not overlap the circle.
  • Do not use an Icon Button for a back button that navigates backwards in the page stack. All Windows Phones are required to have a dedicated hardware back button that should always be used for backward navigation.
  • Use Icon Buttons for the primary, most-used actions in your menu. Some actions are difficult to convey clearly with an icon. If this is the case, consider using a Menu Item instead.
  • Choose icons that have clear meanings when the Application Bar is rotated. The Application Bar automatically handles changes in screen orientation. When the device is in a landscape orientation, the menu is displayed vertically on the side of the screen. The icon buttons are rotated so that they appear upright to the user, but the order of the icons in the list is not changed. It is possible for icon meanings to be confused when this occurs, particularly if two of the icons are mirror images of each other along the Y axis.

Now to the xaml.

Add the following xaml to attribute to the phoneNavigation:PhoneApplicationPage node:

xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone.Shell"



to access the newly added dll reference.



Finally, add the following code inside the node phoneNavigation:PhoneApplicationPage node.



    <phoneNavigation:PhoneApplicationPage.ApplicationBar>
<
shell:ApplicationBar Visible="True" IsMenuEnabled="True">
<
shell:ApplicationBar.Buttons>
<
shell:ApplicationBarIconButton IconUri="/Images/thumbs up.png"></shell:ApplicationBarIconButton>
<
shell:ApplicationBarIconButton IconUri="/Images/thumbs down.png"></shell:ApplicationBarIconButton>
</
shell:ApplicationBar.Buttons>
<
shell:ApplicationBar.MenuItems>
<
shell:ApplicationBarMenuItem x:Name="menuItem1" Text="MenuItem 1"></shell:ApplicationBarMenuItem>
<
shell:ApplicationBarMenuItem x:Name="menuItem2" Text="MenuItem 2"></shell:ApplicationBarMenuItem>
</
shell:ApplicationBar.MenuItems>
</
shell:ApplicationBar>
</
phoneNavigation:PhoneApplicationPage.ApplicationBar>


 



This code sample works with the following image storage structure:



image



The result:



image



If the user clicks on the ellipses on the right side of the Application Bar, it will expand to show the menu items added.



image







If your application is setup to handle both orientations (this is the default behavior) then the menu items and the buttons will rotate appropriately when the phone’s orientation changes.



image





Wednesday, March 24, 2010

Windows Phone 7 Development: Using InputScopes

 

I went to Mix2010 this year and attended Mike Harsh’s talk on Building Windows Phone Applications with Silverlight (Part 1). After the session, I wanted to play around with InputScopes a little bit more, so I decided to try replicate the sample application he showed during the session. It is a really simple application. I figured I would post it since the presentation didn’t cover all of the implementation details.

There is a textbox where the user can type text and a listbox which contains all the available InputScopes. When the user selects an InputScope, it is applied to the textbox. This controls what the virtual keyboard looks like when the user is typing in. For instance, if the user selects the TelephoneNumber InputScope, the keyboard will look like this

image

But if he or she selects the InputScope the keyboard will look like this

image 

So, first to the xaml. This part couldn’t be simpler. Inside the content grid, I added a textbox and a listbox. I also changed the title lable to InpuScopes. That’s it for the xaml

<TextBox x:Name="txtInput" Height="50" VerticalAlignment="Top" />           
<
ListBox Height="580" x:Name="lstScope" HorizontalAlignment="Stretch" Margin="0,66,0,0" VerticalAlignment="Top" Width="460" />


And this is what it looks like. In this screenshot, the listbox is already populated, but we’ll take care of that in a minute in the code behind.



image



In the class constructor I added the bottom two lines. The first one calls a GetNames method which basically returns a list of all the names of the given Enum. The second line simply assigns an event handler to the SelectionChanged event of the listbox. This could have been done in xaml, but I arbitrarily chose to do it in code.



public MainPage()
{
InitializeComponent();

SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;

lstScope.ItemsSource = this.GetNames(typeof(InputScopeNameValue));
lstScope.SelectionChanged += new SelectionChangedEventHandler(lstScope_SelectionChanged);
}


Here is the implementation of the GetNames method. This will take any enumeration type and return a list of strings with all the values.


private  IEnumerable<string> GetNames(Type enumType)
{
if (!enumType.IsEnum)
{
throw new InvalidOperationException("Not an enum type");
}

List<string> nameList = new List<String>();
FieldInfo[] fiArray = enumType.GetFields();
foreach(FieldInfo fi in fiArray)
{
if (fi.FieldType.IsEnum)
{
nameList.Add(fi.Name);
}
}

return nameList;
}


Finally, I implemented the SelectionChanged event handler for the listbox. I basically get the appropriate enum value from the selected string and call the SetInputScope method which essentially sets the input scope for the textbox. That’s it. 


void lstScope_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
InputScopeNameValue val;

if (Enum.IsDefined(typeof(InputScopeNameValue), lstScope.SelectedItem))
{
val = (InputScopeNameValue)Enum.Parse(typeof(InputScopeNameValue), lstScope.SelectedItem.ToString(), true);
SetInputScope(val);
}
}

private void SetInputScope(InputScopeNameValue val)
{
try
{
txtInput.InputScope = new System.Windows.Input.InputScope()
{
Names = { new InputScopeName() { NameValue = val } }
};
}
catch (Exception)
{
//Don't do anything. This fails with some of the InputScopes // Bug?
}
}



Tuesday, March 23, 2010

Windows Phone 7 Book

Charles Petzold has written a Windows Phone 7 book and has posted a free preview here: http://charlespetzold.com/phone/index.html

Just thought I’d spread the word. More to come on Windows Phone 7 development. Happy Coding!