WPF custom panel

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>

 

 

 

 

 

 

 

 

 

posted @ 2024-04-12 00:22  FredGrit  阅读(2)  评论(0编辑  收藏  举报