Posted by: Zeeshan Amjad | February 18, 2010

Using Custom Panel in List Box


We have already saw the example of using item panel template here and here. But in both examples we were using the built in template. If we want to use our own panel then the process is almost same.

Here we are going to use the radial panel. This is define in one of the sample provided by Microsoft and i uses the same code in my example. Here is a complete C# code of our program.

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: using System.Windows;
  6: using System.Windows.Controls;
  7: using System.Windows.Data;
  8: using System.Windows.Documents;
  9: using System.Windows.Input;
 10: using System.Windows.Media;
 11: using System.Windows.Media.Imaging;
 12: using System.Windows.Navigation;
 13: using System.Windows.Shapes;
 14: 
 15: namespace WpfRadialList
 16: {
 17:     /// <summary>
 18:     /// Interaction logic for Window1.xaml
 19:     /// </summary>
 20:     public partial class Window1 : Window
 21:     {
 22:         public Window1()
 23:         {
 24:             InitializeComponent();
 25: 
 26:             List<String> states = new List<string>();
 27: 
 28:             states.Add("Maryland");
 29:             states.Add("California");
 30:             states.Add("Washington");
 31:             states.Add("Virginia");
 32: 
 33:             DataContext = states;
 34:         }
 35:     }
 36: 
 37:     // Class from Microsoft Sample
 38:     public class RadialPanel : Panel
 39:     {
 40:         // This Panel lays its children out in a circle
 41:         // keeping the angular distance from each child
 42:         // equal; MeasureOverride is called before ArrangeOverride.
 43: 
 44:         double _maxChildHeight, _perimeter, _radius, _adjustFactor;
 45: 
 46:         protected override Size MeasureOverride(Size availableSize)
 47:         {
 48:             _perimeter = 0;
 49:             _maxChildHeight = 0;
 50: 
 51:             // Find the tallest child and determine the perimeter
 52:             // based on the width of all of the children after
 53:             // measuring all of the them and letting them size
 54:             // to content by passing Double.PositiveInfinity as
 55:             // the available size.
 56: 
 57:             foreach (UIElement uie in Children)
 58:             {
 59:                 uie.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
 60:                 _perimeter += uie.DesiredSize.Width;
 61:                 _maxChildHeight = Math.Max(_maxChildHeight, uie.DesiredSize.Height);
 62:             }
 63: 
 64:             // If the marginal angle is not 0, 90 or 180
 65:             // then the adjustFactor is needed.
 66: 
 67:             if (Children.Count > 2 && Children.Count != 4)
 68:                 _adjustFactor = 10;
 69: 
 70:             // Determine the radius of the circle layout and determine
 71:             // the RadialPanel's DesiredSize.
 72: 
 73:             _radius = _perimeter / (2 * Math.PI) + _adjustFactor;
 74:             double _squareSize = 2 * (_radius + _maxChildHeight);
 75:             return new Size(_squareSize, _squareSize);
 76:         }
 77: 
 78:         // Perform arranging of children based on 
 79:         // the final size.
 80: 
 81:         protected override Size ArrangeOverride(Size finalSize)
 82:         {
 83:             // Necessary variables.
 84:             double _currentOriginX = 0,
 85:                     _currentOriginY = 0,
 86:                     _currentAngle = 0,
 87:                     _centerX = 0,
 88:                     _centerY = 0,
 89:                     _marginalAngle = 0;
 90: 
 91:             // During measure, an adjustFactor was added to the radius
 92:             // to account for rotated children that might fall outside
 93:             // of the desired size.  Now, during arrange, that extra
 94:             // space isn't needed
 95: 
 96:             _radius -= _adjustFactor;
 97: 
 98:             // Find center of the circle based on arrange size.
 99:             // DesiredSize is not used because the Panel
100:             // is potentially being arranged across a larger
101:             // area from the default alignment values.
102: 
103:             _centerX = finalSize.Width / 2;
104:             _centerY = finalSize.Height / 2;
105: 
106:             // Determine the marginal angle, the angle between
107:             // each child on the circle.
108: 
109:             if (Children.Count != 0)
110:                 _marginalAngle = 360 / Children.Count;
111: 
112:             foreach (UIElement uie in Children)
113:             {
114:                 // Find origin from which to arrange 
115:                 // each child of the RadialPanel (its top
116:                 // left corner.)
117: 
118:                 _currentOriginX = _centerX - uie.DesiredSize.Width / 2;
119:                 _currentOriginY = _centerY - _radius - uie.DesiredSize.Height;
120: 
121:                 // Apply a rotation on each child around the center of the
122:                 // RadialPanel.
123: 
124:                 uie.RenderTransform = new RotateTransform(_currentAngle);
125:                 uie.Arrange(new Rect(new Point(_currentOriginX, _currentOriginY), new Size(uie.DesiredSize.Width, uie.DesiredSize.Height)));
126: 
127:                 // Increment the _currentAngle by the _marginalAngle
128:                 // to advance the next child to the appropriate position.
129: 
130:                 _currentAngle += _marginalAngle;
131:             }
132: 
133:             // In this case, the Panel is sizing to the space
134:             // given, so, return the finalSize which will be used
135:             // to set the ActualHeight & ActualWidth and for rendering.
136: 
137:             return finalSize;
138:         }
139:     }
140: }
141: 

Now we are going to use this panel in our XAML. Here is complete XAML code of our program.

  1: <Window x:Class="WpfRadialList.Window1"
  2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4:     xmlns:local="clr-namespace:WpfRadialList"
  5:     Title="Radial Panel List" Height="300" Width="300">
  6:     <ListBox Margin="5" ItemsSource="{Binding}">
  7:         <ListBox.ItemsPanel>
  8:             <ItemsPanelTemplate>
  9:                 <local:RadialPanel Margin="5"/>
 10:             </ItemsPanelTemplate>
 11:         </ListBox.ItemsPanel>
 12:         <ListBox.ItemTemplate>
 13:             <DataTemplate>
 14:                 <Border Margin="2" BorderBrush="Blue" BorderThickness="1" CornerRadius="3">
 15:                     <TextBlock Margin="2" Text="{Binding}"/>
 16:                 </Border>
 17:             </DataTemplate>
 18:         </ListBox.ItemTemplate>
 19:     </ListBox>
 20: </Window>
 21: 

Note that we also define data template for each item here. Here is a output of this program.

RadialPanelListBoxOutput

Advertisements

Responses

  1. […] We have already seen an example of using Radial Panel use as a item panel template here. Now we are going to apply the radial panel to not only item panel template but also in data […]

  2. […] when creating horizontal list box here. We also saw couple of examples of using Radial Panel here and here.  Now we are going to use the Canvas as a panel. Here is simple piece of XAML code to […]

  3. Hello,

    I am looking on a way to display in scroll list a set of photos and beeing able to select them in a similar way as the Surface application menu does.

    When a picture is scroolled in a ceter window, then a small zoom in occurs, and zoom out when left that center window area.

    I am looking for this behaviour and have no idea what could be the way to implement it.

    Any help or advise aproch ?

    regards
    Serge


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: