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 template. For this example we are going to apply nested data structure because we are going to make nested list. Because every item of list box itself is a list box but we are using item radial panel as a item panel template.
Here is our class to store nested data structure.
1: public class ColorsList2: {3: public ColorsList()4: {5: Colors = new List<string>();6: }7:8: public void AddColor(String color)9: {10: Colors.Add(color);11: }12:13: public List<String> Colors14: { get; set; }15: }16:Here is our complete XAML file that define nested list box and use radial panel.
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="400" Width="400">6: <ListBox Margin="5" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">7: <ListBox.ItemTemplate>8: <DataTemplate>9: <ListBox ItemsSource="{Binding Colors}">10: <ListBox.ItemsPanel>11: <ItemsPanelTemplate>12: <local:RadialPanel Margin="15"/>13: </ItemsPanelTemplate>14: </ListBox.ItemsPanel>15: <ListBox.ItemTemplate>16: <DataTemplate>17: <Ellipse Width="20" Height="10" Fill="{Binding}"/>18: </DataTemplate>19: </ListBox.ItemTemplate>20: </ListBox>21: </DataTemplate>22: </ListBox.ItemTemplate>23: </ListBox>24: </Window>25:Here is our complete C# code of the program. Again we are using the Radial Panel class from Microsoft Sample.
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 WpfRadialList16: {17: /// <summary>18: /// Interaction logic for Window1.xaml19: /// </summary>20: public partial class Window1 : Window21: {22: public Window1()23: {24: InitializeComponent();25:26: List<ColorsList> colorLists = new List<ColorsList>();27:28: ColorsList list1 = new ColorsList();29: list1.AddColor("Blue");30: list1.AddColor("Green");31: list1.AddColor("Red");32: list1.AddColor("Yellow");33: list1.AddColor("Black");34: list1.AddColor("Violet");35:36: colorLists.Add(list1);37:38: ColorsList list2 = new ColorsList();39: list2.AddColor("DarkOrange");40: list2.AddColor("Wheat");41: list2.AddColor("DarkKhaki");42:43: colorLists.Add(list2);44:45: ColorsList list3 = new ColorsList();46: list3.AddColor("DarkMagenta");47: list3.AddColor("DeepPink");48: list3.AddColor("Purple");49: list3.AddColor("DarkOliveGreen");50: list3.AddColor("Brown");51:52: colorLists.Add(list3);53:54: DataContext = colorLists;55: }56: }57:58: public class ColorsList59: {60: public ColorsList()61: {62: Colors = new List<string>();63: }64:65: public void AddColor(String color)66: {67: Colors.Add(color);68: }69:70: public List<String> Colors71: { get; set; }72: }73:74: // Class from Microsoft Sample75: public class RadialPanel : Panel76: {77: // This Panel lays its children out in a circle78: // keeping the angular distance from each child79: // equal; MeasureOverride is called before ArrangeOverride.80:81: double _maxChildHeight, _perimeter, _radius, _adjustFactor;82:83: protected override Size MeasureOverride(Size availableSize)84: {85: _perimeter = 0;86: _maxChildHeight = 0;87:88: // Find the tallest child and determine the perimeter89: // based on the width of all of the children after90: // measuring all of the them and letting them size91: // to content by passing Double.PositiveInfinity as92: // the available size.93:94: foreach (UIElement uie in Children)95: {96: uie.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));97: _perimeter += uie.DesiredSize.Width;98: _maxChildHeight = Math.Max(_maxChildHeight, uie.DesiredSize.Height);99: }100:101: // If the marginal angle is not 0, 90 or 180102: // then the adjustFactor is needed.103:104: if (Children.Count > 2 && Children.Count != 4)105: _adjustFactor = 10;106:107: // Determine the radius of the circle layout and determine108: // the RadialPanel's DesiredSize.109:110: _radius = _perimeter / (2 * Math.PI) + _adjustFactor;111: double _squareSize = 2 * (_radius + _maxChildHeight);112: return new Size(_squareSize, _squareSize);113: }114:115: // Perform arranging of children based on116: // the final size.117:118: protected override Size ArrangeOverride(Size finalSize)119: {120: // Necessary variables.121: double _currentOriginX = 0,122: _currentOriginY = 0,123: _currentAngle = 0,124: _centerX = 0,125: _centerY = 0,126: _marginalAngle = 0;127:128: // During measure, an adjustFactor was added to the radius129: // to account for rotated children that might fall outside130: // of the desired size. Now, during arrange, that extra131: // space isn't needed132:133: _radius -= _adjustFactor;134:135: // Find center of the circle based on arrange size.136: // DesiredSize is not used because the Panel137: // is potentially being arranged across a larger138: // area from the default alignment values.139:140: _centerX = finalSize.Width / 2;141: _centerY = finalSize.Height / 2;142:143: // Determine the marginal angle, the angle between144: // each child on the circle.145:146: if (Children.Count != 0)147: _marginalAngle = 360 / Children.Count;148:149: foreach (UIElement uie in Children)150: {151: // Find origin from which to arrange152: // each child of the RadialPanel (its top153: // left corner.)154:155: _currentOriginX = _centerX - uie.DesiredSize.Width / 2;156: _currentOriginY = _centerY - _radius - uie.DesiredSize.Height;157:158: // Apply a rotation on each child around the center of the159: // RadialPanel.160:161: uie.RenderTransform = new RotateTransform(_currentAngle);162: uie.Arrange(new Rect(new Point(_currentOriginX, _currentOriginY), new Size(uie.DesiredSize.Width, uie.DesiredSize.Height)));163:164: // Increment the _currentAngle by the _marginalAngle165: // to advance the next child to the appropriate position.166:167: _currentAngle += _marginalAngle;168: }169:170: // In this case, the Panel is sizing to the space171: // given, so, return the finalSize which will be used172: // to set the ActualHeight & ActualWidth and for rendering.173:174: return finalSize;175: }176: }177: }178:The output of this program is quite interesting. Here is the output of this program.


[...] 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 define [...]
By: Using Canvas as a ItemPanel Template in ListBox « Zeeshan Amjad's WPF Blog on March 17, 2010
at 10:51 pm