4
votes

Hello there fellow developers! I am working on a Windows Phone 7 app and I can't figure out what I believe is a simple problem for the more seasoned ones. Say I have a layout consisting of two elements: a ListBox (filled with an abundance of items) and a TextBlock (providing the user with some basic instructions).

I want these to be one above the other when the device is in Portrait orientation and I want these to be next to each other when the device orientation changes to Landscape.

For the Portrait orientation I am using a Grid layout manager, as it lets me define the rows' heights like so... row 0 Height="2*", row 1 Height="*"

Listbox sits in row 0, TextBlock in row 1. Now, what would be really neat is to simple change the RowDefinitions into ColumnDefinitions and reassign the listbox/textblock to the grid's columns instead of rows for when the device switches into Landscape.

But that's just my idea. I don't know how to get this done elegantly. Maybe there's a better approach to this? Or maybe this is the correct approach and there is some method built for exactly this purpose?

Thank you for your suggestions!

3
Have you tried this approach? Did it work? Were there any problems?Matt Lacey

3 Answers

3
votes

How about this for the default portrait configuration:-

<Grid>
   <Grid.RowDefinitions>
       <RowDefinition Height="2*" />
       <RowDefinition Height="*" />
   </Grid.RowDefintions>
   <Grid.ColumnDefinitions>
       <ColumnDefinition Width="2*" />
       <ColumnDefinition Width="*" />
   </Grid.ColumnDefinitions>

   <ListBox x:Name="ItemList" Grid.ColumnSpan="2" />
   <TextBlock x:Name="Instructions" Grid.Row="1" Grid.ColumnSpan="2">
      Content
   </TextBlock> 

Then in your OrientationChanged event use:-

if ((e.Orientation & PageOrientation.Portrait) == PageOrientation.Portrait)
{
     Grid.SetRow(ItemList, 0);
     Grid.SetRowSpan(ItemList, 1);
     Grid.SetColumn(ItemList, 0);
     Grid.SetColumnSpan(ItemList, 2);

     Grid.SetRow(Instructions, 1);
     Grid.SetRowSpan(Instructions, 1);
     Grid.SetColumn(Instructions, 0);
     Grid.SetColumnSpan(Instructions, 2);
}
else
{
     Grid.SetRow(ItemList, 0);
     Grid.SetRowSpan(ItemList, 2);
     Grid.SetColumn(ItemList, 0);
     Grid.SetColumnSpan(ItemList, 1);

     Grid.SetRow(Instructions, 0);
     Grid.SetRowSpan(Instructions, 2);
     Grid.SetColumn(Instructions, 1);
     Grid.SetColumnSpan(Instructions, 1);
}
2
votes

For orientation, Visual State Manager works the best.

  1. In Blend, define two states, name them "port" and "land".
  2. Put the "Device" control panel on the Blend workspace.
  3. Record the layouts by switching orientation and designing each layout accordingly.
  4. In the orientation change event, use the following code:

Code:

private void PhoneApplicationPage_OrientationChanged
(object sender, OrientationChangedEventArgs e)
{
   VisualStateManager
    .GoToState(this, e.Orientation.ToString().Substring(0, 4), true);
}
1
votes

I found a nice article in msdn blogs that deals with this sort of layout transformation in a rather straightforward way and explains other approaches as well:

http://blogs.msdn.com/b/ptorr/archive/2010/03/27/strategies-for-dealing-with-orientation-changes.aspx

Why didn't I come across this earlier? :-) Happy coding!