Thursday, February 28, 2013

Silverlight layout resizing

On my current project, we need the pages to be able to resize and display the controls in the most efficient way depending on the current size the user is viewing the application. 

I found one great way here - where using LayoutRoot.SizeChanged and LayoutRoot.LayoutUpdated did a great job in updating the page and making sure that it filled out the screen as expected. What wasn't expected was how it did not work in development for some reason. According to what I was told, it kept looping with another function used and the page wouldn't stop reloading.

Hopefully, I'll be able to get this other way to work, I have mixed the LayoutRoot.SizeChanged with the App.Current.Host.ContentResized where the page will now look to see if the overall browser window has been resized and not look towards the application's main page. Hopefully this will work. (I am so crossing my fingers)

So, the updated way I have it now is:


public MyPage()
{
      InitializeComponent();
    
   // this function is to make sure the controls are the correct size when the page is loading up
     this.Loaded += new RoutedEventHandler(startupLayoutSize);

    // this has the page checking if the overall window has resized, if so then update the sizes of the controls
     App.Current.Host.Content.Resized += new EventHandler(Content_Resized);

// below checks the page size also but it depends on if the overall LayoutRoot of the page has changed
     LayoutRoot.SizeChanged += LayoutRoot_SizeChanged;
}


// even though I am not checking if the main page itself has changed size, I am wanting to
// know the ActualHeight and ActualWidth of the content frame this page is displayed in
MainPage mainPage = (MainPage)Application.Current.RootVisual;


void Content_Resized(object sender, EventArgs e)
{
     Frame pageContainer = mainPage.FindName("PageFrame") as Frame;
     var pageHeight = pageContainer.ActualHeight;
     var pageWidth = pageContainer.ActualWidth;

     this.LayoutRoot.Height = pageHeight;
     this.LayoutRoot.Width = pageWidth;
     
     // many of the controls are in this border and I want them sized proportionally to this border
     var myBorder = pageSideBorder.ActualWidth;

     // I have it set to center horizontally, so when I set the width to 10 less than the actual width
     // of the border, it has the visual effect of adding padding to each side.
     // this does NOT scale the control like ScaleX and ScaleY in a RenderTransform
     controlOne.VerticalAlignment =  VerticalAlignment.Center;
     controlOne.HorizontalAlignment = HorizontalAlignment.Center;
     controlOne.Width = myBorder - 10;
}

     bool updating;
     int layoutUpdated, sizeChanged;
 
// this function also sizes the same controls, but does it when the page loads so they are seen correctly
// when the user first views the page
void startupLayoutSize(object sender, RoutedEventArgs e)
{
     var myBorder = pageSideBorder.ActualWidth;

     controlOne.VerticalAlignment =  VerticalAlignment.Center;
     controlOne.HorizontalAlignment = HorizontalAlignment.Center;
     controlOne.Width = myBorder - 10;
}

// this one does check to see if the size of the LayoutRoot in the main page has changed, but
// it does not look at if the layout is updating
public void LayoutRoot_SizeChanged(object sender, SizeChangedEventArgs e)
{
      MainPage chartMainPage = sender as MainPage;

     if (!updating)
     {
        ++sizeChanged;
        updateContent()
     }
}

// I have the same function but without the EventArgs e
// I will try later to see if I need to do this, but for now it works and that is half of my battle. 
// OK, right now it IS the battle.
private void updateContent( )
{
     Frame pageContainer = mainPage.FindName("PageFrame") as Frame;
     var pageHeight = pageContainer.ActualHeight;
     var pageWidth = pageContainer.ActualWidth;

     this.LayoutRoot.Height = pageHeight;
     this.LayoutRoot.Width = pageWidth;
     
     // many of the controls are in this border and I want them sized proportionally to this border
     var myBorder = pageSideBorder.ActualWidth;

     // I have it set to center horizontally, so when I set the width to 10 less than the actual width
     // of the border, it has the visual effect of adding padding to each side.
     // this does NOT scale the control like ScaleX and ScaleY in a RenderTransform
     controlOne.VerticalAlignment =  VerticalAlignment.Center;
     controlOne.HorizontalAlignment = HorizontalAlignment.Center;
     controlOne.Width = myBorder - 10;
}

Now, hopefully this "solution" will work - and then I have this as reference for later. If not - then this is a reference of what I started with and was still an oops moment. (and will be updated)

No comments:

Post a Comment