by JustinAngel via Justin myJustin = new Microsoft.Silverlight.Justin(); on 11/6/2008 12:58:51 AM
Hi Folks,
I’d like for us to talk about one of the new controls in the Silverlight Toolkit – WrapPanel.
In the following article we’ll deep dive into WrapPanel and see how it behaves in different situations.
Setup
1. Create a new project.
2. Add a reference to the Silverlight Controls assembly (Microsoft.Windows.Controls.dll) which can be downloaded at http://codeplex.com/Silverlight.
3. Look under "Custom Controls" In the Blend Asset Library.
4. Add a WrapPanel to the Page.
And here's the XAML we got:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="SilverlightControlsNovember2008.WrapPanelPage"
d:DesignWidth="640" d:DesignHeight="480"
xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">
<Grid x:Name="LayoutRoot" Background="#FFFFFFFF">
<controls:WrapPanel />
</Grid>
</UserControl>
WrapPanel with Horizontal Orientation
Let’s have a look at a basic StackPanel usage.
<StackPanel Height="300" Width="300" Background="#FFE1E1E1">
<Image Height="100" Width="100" Source="Cookie1.png"/>
<Image Height="100" Width="100" Source="Cookie2.png"/>
<Image Height="100" Width="100" Source="Cookie3.png"/>
<Image Height="100" Width="100" Source="Cookie4.png"/>
<Image Height="100" Width="100" Source="Cookie5.png"/>
</StackPanel>
We’ll Stack 5 cookies on top of each other and we’ll get this display:
So each cookie has a height & Width of 100 pixels over a 100 pixels. StackPanel arranges them top-down. So cookie #1 is first, followed by cookie #2 and all the way to cookie #5.
However, our StackPanel has a width of 300, and you can see all that wasted space in the grey background of our StackPanel.
We’d like a way to stack the cookies from Left-To-right until there isn’t anymore place to add another cookie.
In comes – WrapPanel.
We’ll drag & drop our 7 cookies from the solution explorer to the WrapPanel.
By default, Blend sets the Image.StrechMode to fill, which we’ll want to change back to None.
We’ll select the cookie and set it’s StretchMode.Nonde.
And we’ll get a normal sized Cookie.
We’ll repeat this for cookie #2.
We can see here that Cookie #2 has been aligned to the right of cookie #1 that preceded it. Let’s add Cookie #3.
Again, Cookie #3 got added to the right of Cookie #2 which is on the right of cookie #1.
Let’s add cookie #4.
We can see that Cookie #4 didn’t have any more “place” on the first row, so WrapPanel added another row for it and placed it there.
Let’s fill the WrapPanel with 7 Cookies.
If we run this, we’ll get the same picture, just running the browser.
Here’s the XAML Blend generated for us:
<controls:WrapPanel Height="300" Width="300">
<Image Source="Cookie1.png" Stretch="None" Height="100" Width="100"/>
<Image Source="Cookie2.png" Stretch="None" Height="100" Width="100"/>
<Image Source="Cookie3.png" Stretch="None" Height="100" Width="100"/>
<Image Source="Cookie4.png" Stretch="None" Height="100" Width="100"/>
<Image Source="Cookie5.png" Stretch="None" Height="100" Width="100"/>
<Image Source="Cookie6.png" Stretch="None" Height="100" Width="100"/>
<Image Source="Cookie7.png" Stretch="None" Height="100" Width="100"/>
</controls:WrapPanel>
We can see that our WrapPanel was able to place as many items as it could at every row and when it needed more space, it added another row.
That behavior is specified by Orientation.Horizontal which is the default for WrapPanel. So setting WrapPanel.Orientation=Orientation.Horizontal would be equivalent to the default value. Let’s do that anyway though.
-->
We get the following XAML:
<controls:WrapPanel Height="300" Width="300" Orientation="Horizontal">
Which looks exactly the same as did the default sample:
So now we have 7 Cookies properly Wrapped. 7 Cookies.
http://www.youtube.com/watch?v=u7hTkzEwFZ0
WrapPanel with Vertical Orientation
the keen sighted might have noticed that we also have Orientation.Vertical as an option. Let’s set WrapPanel.Orientation to that and see how it arranges our controls.
<controls:WrapPanel Height="300" Width="300" Orientation="Vertical">
And here’s how the WrapPanel looks like:
Our 7 Cookies are now aligned top-to-bottom.
First, WrapPanel places Cookie #1 in the top left corner. Than it places Cookie #2 and Cookie #3 below it.
Once Cookie #4 needs to get placed, there’s no room left on the first column. So WrapPanel opens another column and starts placing Cookies #4, #5 & #6 in that column.
And once there’s no more room left in the second column, WrapPanel places Cookie #7 in the third column.
Horizontal WrapPanel Items with Vertical alignment
A problem might arise though, some of our controls might not be in the same size as others.
Let’s assume that cookie #5 isn’t 100x100 pixels in Height & Width. Rather, let’s assume that cookie #5 is 150 pixels in Height.
<controls:WrapPanel Height="400" Width="350" Orientation="Horizontal">
<Image Source="Cookie1.png" Stretch="None"/>
<Image Source="Cookie5.png" Stretch="Fill" Height="200" Width="100"/>
We can see that the WrapPanel still makes sense. However, Cookie #4 & Cookie #6 are aligned to the center of Row #2 (which contains Cookies 4, 5 & 6).
In real-world scenarios we might like to have different alignments for Cookies #4 & #6.
In Blend, we’ll select Cookie #4 and set it’s VerticalAlignment to Top and we’ll select Cookie #6 and set it’s VerticalAlignment to Bottom.
And now, Once we run our sample, we can see this image:
So Cookie #4 was aligned to the Top of the row, and Cookie #6 was aligned to the bottom of the row.
And we got the following XAML:
<Image Source="Cookie4.png" Stretch="None" Height="100" Width="100" VerticalAlignment="Top"/>
<Image Source="Cookie6.png" Stretch="None" Height="100" Width="100" VerticalAlignment="Bottom"/>
Vertical WrapPanel Items with Horizontal alignment
A similar problem can arise in a WrapPanel that has a Vertical Orientation.
Let’s take our previous Vertical WrapPanel, and set the width of Cookie #5 to 200.
<controls:WrapPanel Height="350" Width="400" Orientation="Vertical">
<Image Source="Cookie4.png" Stretch="None" Height="100" Width="100" />
<Image Source="Cookie5.png" Stretch="Fill" Height="100" Width="200"/>
Which would render like so:
We can see that in this sample, Cookie #4 and Cookie #6 were both aligned Center in terms of HorizontalAlignment.
Let’s set Cookie #4 HorizontalAlignment to Left, and Cookie #6 HorizontalAlignment to Right.
Let’s run the sample.
And we can indeed see that Cookie #4 is aligned to the Left of the 2nd column and Cookie #6 is aligned to the Right of the 2nd column.
<Image Source="Cookie4.png" Stretch="None" Height="100" Width="100" HorizontalAlignment="Left" />
<Image Source="Cookie6.png" Stretch="None" Height="100" Width="100" HorizontalAlignment="Right"/>
Changing ListBox.ItemsPanel to WrapPanel
Let’s do something a bit more interesting with our new WrapPanel than just put cookies in it. Let’s put our cookies in a ListBox!
First, we’ll add a new Listbox to our Page.
Next, we’d like to say “each item in this ListBox is an Image”.
Right click on Listbox –> Edit Other Templates –> Edit Generated Items (ItemTemplate) –> Create Empty.
What we’re doing here is saying “well, the default template for each of our items is a bit different that you’d expect”.
We’ll name the new DataTemplate “CookieItemTemplate”.
And this is what we see now:
There’s an Empty <Grid> in our new DataTemplate. Since we want to display an Image we’ll add an Image control.
Next, we’d like our Image to be 100x100 pixels.
And finally, we’ll introduce some DataBinding. We’d like to DataBind our Image.Source property to whatever is bound to the DataTemplate.
click “Advanced property options” next to source.
Select “Custom Expression”
And put in “{Binding}”.
and here’s the XAML blend generated for us:
<ListBox x:Name="cookies" Margin="0,0,0,0" Height="300" Width="300" ItemTemplate="{StaticResource CookieItemTemplate}"/>
And here’s the CookieItemTemplate resouce:
<UserControl.Resources>
<DataTemplate x:Key="CookieItemTemplate">
<Grid>
<Image Width="100" Height="100" Source="{Binding}"/>
</DataTemplate>
</UserControl.Resources>
Next step before we run this sample is to specify a ListBox.ItemsSource (the URIs for all our images).
void WrapPanelPage_Loaded(object sender, RoutedEventArgs e)
{
cookies.ItemsSource = new BitmapImage[]
new BitmapImage(new Uri("Cookie1.png", UriKind.Relative)),
new BitmapImage(new Uri("Cookie2.png", UriKind.Relative)),
new BitmapImage(new Uri("Cookie3.png", UriKind.Relative)),
new BitmapImage(new Uri("Cookie4.png", UriKind.Relative)),
new BitmapImage(new Uri("Cookie5.png", UriKind.Relative)),
new BitmapImage(new Uri("Cookie6.png", UriKind.Relative)),
new BitmapImage(new Uri("Cookie7.png", UriKind.Relative))
};
}
This is a pretty scary syntax. honestly, it’s just the syntax for a “Image.Source={Binding}”. There’s nothing really special here and you should just take it for what it is – the syntax the framework requires in this case.
Finally, we can run our Listbox:
Most cookies aren’t visible at all. We can scroll to see them, but that’s not quite the effect we’re looking for here.
This would be an appropriate place to use a WrapPanel. To do that we’ll edit the ListBox.ItemsPanel.
Let’s go back to Blend, select our ListBox, Right click it and select “Edit Other Templates –> Edit Layout Items (ItemsPanel) –> Create empty…”.
We’ll name it “cookiesItemsPanel”.
And here’s what we got:
What we want to do here is tell our ListBox “well, don’t use a grid, use a WrapPanel”
So, we’ll delete our Grid, and put in a WrapPanel instead of it.
Now, let’s re-run our application.
Hmm… this ScrollBar doesn’t work for us. So let’s specify we don’t need it.
And re-run our application.
And here we go – a ListBox that uses a WrapPanel instead of the default layout.
And here’s the ListBox blend genrated for us:
<ListBox x:Name="cookies" Height="330" Width="330" ItemTemplate="{StaticResource CookieItemTemplate}" ItemsPanel="{StaticResource CookiesItemsPanel}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
Our ItemTemplate & ItemsPanelTemplate:
<Grid >
<Image Source="{Binding}" Width="100" Height="100"/>
<ItemsPanelTemplate x:Key="CookiesItemsPanel">
<controls:WrapPanel/>
</ItemsPanelTemplate>
And code-behind:
-- Justin-Josef Angel
Microsoft Silverlight Program Manager
Original Post: Silverlight Toolkit: WrapPanel
The content of the postings is owned by the respective author. Silverlight Feeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on Silverlight Feeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.