Region resizing

Topics: Prism v2 - Silverlight 3
Sep 18, 2009 at 2:32 PM
Edited Sep 18, 2009 at 2:33 PM

Hello,

(Silverlight 3 - Composite Application (Prism))

I have a composite application consisting of regions inside a tabcontrol.

When I resize my window, the tabcontrol follows and resize itself, the region resizes itself as well but its content only resizes itself horizontally.

My region is simply declared like this :

<ItemsControl Name="AgentMngtRegion" Regions:RegionManager.RegionName="AgentMngtRegion" />

and my module simply register itself to the region like this :

 this.regionManager.Regions["AgentMngtRegion"].Add(new Main.MainPage());

My MainPage is a usercontrol with a grid with 3 rows :

<Grid x:Name="LayoutRoot" Background="#f5f5f5">
<Grid.RowDefinitions>
<RowDefinition Height="115" />
<RowDefinition Height="*" MinHeight="100" />
<RowDefinition Height="445" />
</Grid.RowDefinitions>

Basically the Row #1 (Height=*) should resize itself and take the remaining space but it doesn't. It stays always at 100px.

 

Any ideas?

Thanks,

Alex

 

Sep 18, 2009 at 3:35 PM

Hi Alex,

I actually addressed this issue recently in my http://multitargeting.CodePlex.com project, I wanted all of my applications (WPF, Silverlight and Winforms) to have the same behaviors using PRISM.   You'll find on the home page of the referenced link that there is a video clip showing it in action.

<UserControl x:Class="Demo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Regions="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"            
    >
    <Grid Width="800" Height="550"
          x:Name="LayoutRoot"
          RenderTransformOrigin="0.5 0.5">
       
        <ItemsControl Regions:RegionManager.RegionName="MainRegion" />
   
        <Grid.RenderTransform>
            <ScaleTransform x:Name="PageScale" ScaleX="1" ScaleY="1"/>
        </Grid.RenderTransform>
    </Grid>
</UserControl>

I can't recall the blog I got this information from (to give credit where credit is due) but the above RenderTransform works in conjunction with the following code behind in the MainPage (shell).

public partial class MainPage : UserControl
{
    private double originalWidth;
    private double originalHeight;
    private double originalAspectRatio;

    public MainPage()
    {
        InitializeComponent();

        // wire up the event handler. This is a great addition
        // to silverlight, as you used to have to hook into the
        // browser event yourself
        SizeChanged += new SizeChangedEventHandler(Page_SizeChanged);
    }

    private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (originalAspectRatio == 0)
        {
            originalWidth = LayoutRoot.Width + 10;
            originalHeight = LayoutRoot.Height + 10;
            originalAspectRatio = originalWidth / originalHeight;
        }

        if (e.NewSize.Width < originalWidth || e.NewSize.Height < originalHeight)
        {
            // don't shrink
            PageScale.ScaleX = 1.0;
            PageScale.ScaleY = 1.0;
        }
        else
        {
            // resize keeping aspect ratio the same
            if (e.NewSize.Width / e.NewSize.Height > originalAspectRatio)
            {
                // height is our constraining property
                PageScale.ScaleY = e.NewSize.Height / originalHeight;
                PageScale.ScaleX = PageScale.ScaleY;
            }
            else
            {
                // either width is our constraining property, or the user
                // managed to nail our aspect ratio perfectly.
                PageScale.ScaleX = e.NewSize.Width / originalWidth;
                PageScale.ScaleY = PageScale.ScaleX;
            }
        }
    }
}

Where the above fires for every resize event I found that child views only fire once.   I took advantage of this fact to solve a problem with my treeviews extending beyond my region versus showing scrollbars (I use a DockPanel on the WPF side).   If you define your Width and Height then this is not a problem however we don't want to set any widths/heights for obvious reasons.

So in my PresenterBase class I have the following (excerpt) that wires up the views SizeChanged event:

[InjectionConstructor]
public PresenterBase(IView view, IPresentationModel model, IUnityContainer container)
{
    try
    {
        // For logging purposes
        ModuleName = GetType().FullName;

        // Setter injection is not available until after the constructor
        // so we'll set them manually
        Error = container.Resolve<IError>();
        Logger = container.Resolve<ILoggerFacade>();

        // Set the presenter with a reference to the container
        Container = container;

        // Set the Presenter with a reference to the model
        Model = model;

        if ((TView)view is UserControl)
        {
#if !WinForm
            // WPF/Silverlight have SizeChanged event
            // Provide means to notify User Controls that their size has been set
            ((TView)view).SizeChanged += (object sender, SizeChangedEventArgs e) =>
                {
                    OnViewSizeSet(sender, e);
                };
#endif
        }

You find in Modules\Views\Data\LocalDataPresenter the following override:

/// <summary>
/// Called when [view size set].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.SizeChangedEventArgs"/> instance containing the event data.</param>
protected override void OnViewSizeSet(object sender, SizeChangedEventArgs e)
{
    base.OnViewSizeSet(sender, e);

    // Set the treeview to fit the entire control
    tvwLocalDataSource.Width = (int)e.NewSize.Width;
    tvwLocalDataSource.Height = (int)e.NewSize.Height;
}

Which effectively sets the treeview width and height (only one time) and after that the RenderTransform adjusts its dimensions.

 

 

 

 

 

 

 

Sep 24, 2009 at 2:38 PM

Nice! but the problem with that code is it doesn't resize the section but "scales" the controls so they are bigger!

In my case, I just want the row marked Height="*" to take the remaining space.

It's kinda like the ItemsControl resizes its content horizontally but not vertically...

I'll try to play around with the SizeChanged event.

Other ideas?

Alex

 

Sep 24, 2009 at 3:32 PM

I got it working after stumbling on this thread : http://compositewpf.codeplex.com/Thread/View.aspx?ThreadId=28522

 Just adding this to my ItemsControl did the trick!

 <ItemsControl.ItemsPanel>
 <ItemsPanelTemplate>
  <controlsToolkit:DockPanel />
 </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

 Thanks all for your help!