using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows;
namespace WpfApp54
{
class RadialPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
Size maxSize = Size.Empty;
foreach (UIElement child in Children)
{
child.Measure(availableSize);
maxSize = new Size(Math.Max(maxSize.Width, child.DesiredSize.Width),
Math.Max(maxSize.Height, child.DesiredSize.Height));
}
return new Size(double.IsPositiveInfinity(availableSize.Width) ?
maxSize.Width * 2 : availableSize.Width,
double.IsPositiveInfinity(availableSize.Height) ?
maxSize.Height * 2 : availableSize.Height);
}
public double StartAngle
{
get { return (double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
// Using a DependencyProperty as the backing store for StartAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register("StartAngle", typeof(double), typeof(RadialPanel),
new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
protected override Size ArrangeOverride(Size finalSize)
{
var count = Children.Count;
if (count > 0)
{
Point center = new Point(finalSize.Width / 2, finalSize.Height / 2);
double step = 360 / count;
int index = 0;
foreach (UIElement element in Children)
{
double angle = StartAngle + step * index++;
angle = (90 - angle) * Math.PI / 180;
Rect rc = new Rect(new Point(center.X - element.DesiredSize.Width / 2 +
(center.X - element.DesiredSize.Width / 2) * Math.Cos(angle),
center.Y - element.DesiredSize.Height / 2 -
(center.Y - element.DesiredSize.Height / 2) * Math.Sin(angle)),
element.DesiredSize);
element.Arrange(rc);
}
}
return finalSize;
}
}
}
//xaml
<Window x:Class="WpfApp54.MainWindow"
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"
xmlns:local="clr-namespace:WpfApp54"
mc:Ignorable="d" WindowState="Maximized"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Slider Margin="4" Maximum="360" x:Name="_startAngle" Grid.Row="1"/>
<local:RadialPanel StartAngle="{Binding Value,ElementName=_startAngle}">
<Ellipse Fill="Red" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Green" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Blue" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Red" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Yellow" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Brown" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Orange" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Red" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="LightBlue" Stroke="Black"
StrokeThickness="2" Width="40" Height="40"/>
<Ellipse Fill="Red" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Cyan" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
<Ellipse Fill="Red" Stroke="Black" StrokeThickness="2"
Width="40" Height="40"/>
</local:RadialPanel>
</Grid>
</Window>
![]()
![]()
![]()
![]()