using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace App8 { public class orbitpanel:Panel { int i = 0; public int orbitsnunber { get { return (int)GetValue(OrbitsProperty); } set { SetValue(OrbitsProperty,value); } } public static readonly DependencyProperty OrbitsProperty = DependencyProperty.Register("orbitsnunber", typeof(int), typeof(orbitpanel), new PropertyMetadata(1, OnOrbitsChanged)); private static void OnOrbitsChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { if ((int)e.NewValue < 1) { throw new ArgumentException( "Orbits must be greater than or equal to 1."); } } public static int GetOrbit(DependencyObject obj) { return (int)obj.GetValue(OrbitProperty); } public static void SetOrbit(DependencyObject obj, int value) { obj.SetValue(OrbitProperty, value); } public static readonly DependencyProperty OrbitProperty =DependencyProperty.RegisterAttached("Orbit", typeof(int), typeof(orbitpanel), new PropertyMetadata(0)); protected override Size MeasureOverride(Size availableSize) { var sortedItems = SortElements(); double max = 0.0; foreach (List<UIElement> orbitItems in sortedItems) { if (orbitItems.Count > 0) { foreach (UIElement element in orbitItems) { element.Measure(availableSize); if (element.DesiredSize.Width > max) max = element.DesiredSize.Width; if (element.DesiredSize.Height > max) max = element.DesiredSize.Height; } } } Size desiredSize = new Size(max * orbitsnunber * 2, max * orbitsnunber * 2); if (double.IsInfinity(availableSize.Height) || double.IsInfinity(availableSize.Width)) return desiredSize; else return availableSize; } protected override Size ArrangeOverride(Size finalSize) { var sortedItems = SortElements(); double orbitSpacing = CalculateOrbitSpacing(finalSize); foreach (List<UIElement> orbitItems in sortedItems) { int count = orbitItems.Count; if (count > 0) { double circumference = 2 * Math.PI * orbitSpacing * (i + 1); double slotSize = Math.Min(orbitSpacing, circumference / count); double maxSize = Math.Min(orbitSpacing, slotSize); double angleIncrement = 360 / count; double currentAngle = 0; Point centerPoint = new Point(finalSize.Width / 2, finalSize.Height / 2); foreach (UIElement element in orbitItems) { double angle = Math.PI / 180 * (currentAngle - 90); double left = orbitSpacing * (i + 1) * Math.Cos(angle); double top = orbitSpacing * (i + 1) * Math.Sin(angle); Rect finalRect = new Rect( centerPoint.X + left - element.DesiredSize.Width / 2, centerPoint.Y + top - element.DesiredSize.Height / 2, element.DesiredSize.Width, element.DesiredSize.Height); element.Arrange(finalRect); currentAngle += angleIncrement; } } } return base.ArrangeOverride(finalSize); } private List<UIElement>[] SortElements() { var list = new List<UIElement>[orbitsnunber]; for (int i = 0; i < orbitsnunber; i++) { if (i == orbitsnunber - 1) list[i] = (from UIElement child in Children where GetOrbit(child) >= i select child).ToList<UIElement>(); else list[i] = (from UIElement child in Children where GetOrbit(child) == i select child).ToList<UIElement>(); } return list; } private double CalculateOrbitSpacing(Size availableSize) { double constrainingSize = Math.Min( availableSize.Width, availableSize.Height); double space = constrainingSize / 2; return space / orbitsnunber; } } }
使用方法
<local:orbitpanel orbitsnunber="1">
<Image x:Name="image" local:orbitpanel.Orbit="0" HorizontalAlignment="Left" Height="166" PointerEntered="image_PointerEntered_1" PointerExited="image_PointerExited_1" Margin="449,349,0,0" VerticalAlignment="Top" Width="261" Source="http://img.trip.elong.com/guide/attachments/bc/d1/be/bcd1bef731bbde7796bb55edbed0fc1f.jpg" RenderTransformOrigin="0.5,0.5">
</Image>
<Image local:orbitpanel.Orbit="0" HorizontalAlignment="Left" Height="166" PointerEntered="image_PointerEntered_1" PointerExited="image_PointerExited_1" Margin="449,349,0,0" VerticalAlignment="Top" Width="261" Source="http://img.trip.elong.com/guide/attachments/bc/d1/be/bcd1bef731bbde7796bb55edbed0fc1f.jpg" RenderTransformOrigin="0.5,0.5">
</Image>
<Image local:orbitpanel.Orbit="0" HorizontalAlignment="Left" Height="166" PointerEntered="image_PointerEntered_1" PointerExited="image_PointerExited_1" Margin="449,349,0,0" VerticalAlignment="Top" Width="261" Source="http://img.trip.elong.com/guide/attachments/bc/d1/be/bcd1bef731bbde7796bb55edbed0fc1f.jpg" RenderTransformOrigin="0.5,0.5"> </Image>
<Image local:orbitpanel.Orbit="0" HorizontalAlignment="Left" Height="166" PointerEntered="image_PointerEntered_1" PointerExited="image_PointerExited_1" Margin="449,349,0,0" VerticalAlignment="Top" Width="261" Source="http://img.trip.elong.com/guide/attachments/bc/d1/be/bcd1bef731bbde7796bb55edbed0fc1f.jpg" RenderTransformOrigin="0.5,0.5">
</Image>
<Image local:orbitpanel.Orbit="0" HorizontalAlignment="Left" Height="166" PointerEntered="image_PointerEntered_1" PointerExited="image_PointerExited_1" Margin="449,349,0,0" VerticalAlignment="Top" Width="261" Source="http://img.trip.elong.com/guide/attachments/bc/d1/be/bcd1bef731bbde7796bb55edbed0fc1f.jpg" RenderTransformOrigin="0.5,0.5">
</Image>
<Image local:orbitpanel.Orbit="0" HorizontalAlignment="Left" Height="166" PointerEntered="image_PointerEntered_1" PointerExited="image_PointerExited_1" Margin="449,349,0,0" VerticalAlignment="Top" Width="261" Source="http://img.trip.elong.com/guide/attachments/bc/d1/be/bcd1bef731bbde7796bb55edbed0fc1f.jpg" RenderTransformOrigin="0.5,0.5">
</Image>
</local:orbitpanel>