views:

118

answers:

3

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!

+2  A: 

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);
}
AnthonyWJones
Also be sure to set the orientation when navigating to and/or page load as you can't be sure what orientation the device will be when navigating (or returning to) that page.
Matt Lacey
@Matt: Good point best place the above code in a function and call from both code locations.
AnthonyWJones
This looks promising. I tried but I can't get the containing grid to resize properly - to stretch horizontally to reach out to the right side of the screen. Its height adjusts, its contents (the ItemList and Instructions) are rearranged properly, but it retains its width so I am left with a lot of blank space to the right of the Instructions. I tried calling `InvalidateArrange();` `UpdateLayout();` but nothing helps.
Peter Perháč
@Peter: I can't explain that behaviour I've tested my code on the emulator and it works fine.
AnthonyWJones
oh :-( i was struggling with it for quite a while and then gave up in hope that maybe you will shed some light on this. I moved on to preparing a page with a Bing Map on it and this one behaves odd too. The map looks okay in the designer but when I launch the app in emulator, the map shrinks to 100x100 (or so) and I can't get it to grow! Seems like there must be some other problem in the markup or code that avoids my notice. Thank for your help, I didn't know about those static methods on Grid. Once I resolve the other issue, this code should work just fine, like it works for you. Cheers!
Peter Perháč
plus, i found a nice article in msdn blogs that deals with this sort of layout transformation in a slightly simpler way (since it is a slightly different case) :-)
Peter Perháč
+1  A: 

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);
}
Sergey Aldoukhov
This sounds straightforward, but we are not using Blend...
Peter Perháč
Blend is an awesome tool for WP7 dev, and I highly recommend you at least check it out :) You should still be able to do what's described in this answer without blend, though. Have a look at this thread for a start - http://forums.silverlight.net/forums/p/30033/98891.aspx
Blakomen
+1  A: 

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!

Peter Perháč