Silverlight自定义饼图

1:XAML

<Style TargetType="local:PieChart">
        <Setter Property="Foreground" Value="#FF767676" />
        <Setter Property="Palette">
            <Setter.Value>
                <local:PaletteCollection>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="#FF25a0db" />
                        <Setter Property="Stroke" Value="#FFFFFF" />
                    </Style>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="#FF9cd60f" />
                        <Setter Property="Stroke" Value="#FFFFFF" />
                    </Style>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="#FFeb7a2a" />
                        <Setter Property="Stroke" Value="#FFFFFF" />
                    </Style>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="#FFd4df32" />
                        <Setter Property="Stroke" Value="#FFFFFF" />
                    </Style>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="#FFcc0000" />
                        <Setter Property="Stroke" Value="#FFFFFF" />
                    </Style>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="#FFE8BC34" />
                        <Setter Property="Stroke" Value="#FFFFFF" />
                    </Style>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="#FF00ABA9" />
                        <Setter Property="Stroke" Value="#FFFFFF" />
                    </Style>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="#FF339933" />
                        <Setter Property="Stroke" Value="#FFFFFF" />
                    </Style>
                </local:PaletteCollection>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:PieChart">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>

                        <Grid x:Name="gChart" Grid.Column="0">

                        </Grid>

                        <Grid x:Name="gLegend" Grid.Column="1" Width="{TemplateBinding LegendWidth}" >
                            <ScrollViewer Margin="20,0,0,0" BorderThickness="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
                                <StackPanel x:Name="spLegend" Orientation="Vertical"  />
                            </ScrollViewer>
                        </Grid>

                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>




2:C#后台

    /// <summary>
    /// 饼状图控件
    /// 参数说明:
    /// Label:类型标签,传值的类型标签,如Dictionary的Key;
    /// Value:值,如Dictionary的Value;
	/// ShowLabel:是否显示饼图标签;
	/// ShowLegend:是否显示图例;
	/// Palette:饼图的颜色板,可以用PaletteCollection类添加,默认颜色有8种;
	/// LegendWidth:图例的宽度;
	/// ItemsSource:饼图的数据源;
    /// 
    /// author:hzw
    /// time:2013/08/20
    /// </summary>
    [TemplatePart(Name = "gLegend", Type = typeof(Grid))]
    [TemplatePart(Name = "gChart", Type = typeof(Grid))]
    [TemplatePart(Name = "spLegend", Type = typeof(StackPanel))]
    public class PieChart : Control
    {
        /// <summary>
        /// 类型标签
        /// </summary>
        public string Label { get; set; }
        
        /// <summary>
        /// 值
        /// </summary>
        public string Value { get; set; }
        FxChart c = new FxChart("",null,"");
        
        /// <summary>
        /// 构造函数
        /// </summary>
        public PieChart()
        {
            this.DefaultStyleKey = typeof(PieChart);
            SizeChanged += new SizeChangedEventHandler(PieChart_SizeChanged);
        }

        /// <summary>
        /// 尺寸变化事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PieChart_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (ItemsSource != null)
            {
                BindData();
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            if (ItemsSource != null)
            {
                BindData();
            }
        }

        #region 依赖性属性设置

        public static readonly DependencyProperty ShowLabelProperty = DependencyProperty.Register("ShowLabel", typeof(bool), typeof(PieChart), new PropertyMetadata(false, new PropertyChangedCallback(OnShowLabelPropertyChanged)));
        /// <summary>
        /// 显示标签
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnShowLabelPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PieChart obj = (PieChart)d;
            obj.BindData();
        }
        public bool ShowLabel
        {
            get { return (bool)GetValue(ShowLabelProperty); }
            set { SetValue(ShowLabelProperty, value); this.BindData(); }
        }

        public static readonly DependencyProperty ShowLegendProperty = DependencyProperty.Register("ShowLegend", typeof(bool), typeof(PieChart), new PropertyMetadata(false, new PropertyChangedCallback(OnShowLegendPropertyChanged)));
        /// <summary>
        /// 是否显示图例
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnShowLegendPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PieChart obj = (PieChart)d;
            obj.BindData();
        }
        public bool ShowLegend
        {
            get { return (bool)GetValue(ShowLegendProperty); }
            set { SetValue(ShowLegendProperty, value); this.BindData(); }
        }

        public static readonly DependencyProperty PaletteProperty = DependencyProperty.Register("Palette", typeof(PaletteCollection), typeof(PieChart), new PropertyMetadata(new PaletteCollection()));
        /// <summary>
        /// 调色板
        /// </summary>
        public PaletteCollection Palette
        {
            get { return (PaletteCollection)GetValue(PaletteProperty); }
            set
            {
                SetValue(PaletteProperty, value);
            }
        }

        public static readonly DependencyProperty LegendWidthProperty = DependencyProperty.Register("LegendWidth", typeof(double), typeof(PieChart), new PropertyMetadata((double)80, new PropertyChangedCallback(OnLegendWidthPropertyChanged)));
        /// <summary>
        /// 图例宽度
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnLegendWidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PieChart obj = (PieChart)d;
            obj.BindData();
        }
        public double LegendWidth
        {
            get { return (double)GetValue(LegendWidthProperty); }
            set
            {
                SetValue(LegendWidthProperty, value);
            }
        }


        public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(PieChart), new PropertyMetadata(null, new PropertyChangedCallback(OnItemsSourcePropertyChanged)));
        /// <summary>
        /// 数据源
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PieChart obj = (PieChart)d;
            obj.BindData();
        }
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set
            {
                SetValue(ItemsSourceProperty, value);
                BindData();
            }
        }

        #endregion

        const double ChartSpace = 100;
        const double LabelSpace = 1;
        List<Path> _List = new List<Path>();

        #region 绑定数据源
        /// <summary>
        /// 绑定数据
        /// </summary>
        private void BindData()
        {
            string labelPath = this.Label;
            string valuePath = this.Value;

            if (this.ActualWidth == double.NaN || this.ActualWidth == 0) return;

            Grid gLegend = (Grid)this.GetTemplateChild("gLegend");
            Grid gChart = (Grid)this.GetTemplateChild("gChart");
            StackPanel spLegend = (StackPanel)this.GetTemplateChild("spLegend");

            if (gLegend == null || gChart == null || spLegend == null) return;

            gChart.Children.Clear();
            spLegend.Children.Clear();
            _List.Clear();

            gLegend.Visibility = ShowLegend ? Visibility.Visible : Visibility.Collapsed;

            double chartSpace = ChartSpace;

            //饼图位置
            double chartWidth = this.ActualWidth - (ShowLegend ? LegendWidth : 0);
            Point centerPoint = new Point(chartWidth / 2, this.ActualHeight / 2);
            if (chartWidth > this.ActualHeight) chartWidth = this.ActualHeight;
            if (ShowLabel && chartWidth > chartSpace) chartWidth = chartWidth - chartSpace;

            //初始角度
            double startAngle = 0;
            //初始点
            Point startPoint = new Point(centerPoint.X, centerPoint.Y - (chartWidth / 2));

            if (ItemsSource != null && !string.IsNullOrEmpty(labelPath) && !string.IsNullOrEmpty(valuePath))
            {
                //取总数
                double sum = 0;
                foreach (object obj in ItemsSource)
                {
                    PropertyInfo piLabel = obj.GetType().GetProperty(labelPath);
                    PropertyInfo piValue = obj.GetType().GetProperty(valuePath);
                    if (piLabel == null)
                        throw new Exception("标签错误!");
                    if (piValue == null)
                        throw new Exception("值错误!");
                    object v = piValue.GetValue(obj, null);
                    if (v != null)
                    {
                        sum += double.Parse(v.ToString());
                    }
                }

                int paletteIndex = 0;
                Brush fill = new SolidColorBrush(Color.FromArgb(0xFF, 0xBA, 0xBA, 0xBA));
                //Brush stroke = new SolidColorBrush(Colors.White);
                Style style = new Style();
                style.Setters.Add(new Setter { Property = Path.FillProperty, Value = new SolidColorBrush(Color.FromArgb(0xFF, 0xBA, 0xBA, 0xBA)) });
                style.Setters.Add(new Setter { Property = Path.StrokeProperty, Value = new SolidColorBrush(Colors.White) });
                foreach (object obj in ItemsSource)
                {
                    //获取调色板
                    if (Palette != null && Palette.Count > 0)
                    {
                        style = Palette[paletteIndex];
                        foreach (Setter setter in style.Setters)
                        {
                            if (setter.Property == Path.FillProperty)
                                fill = (Brush)setter.Value;
                            //if (setter.Property == Path.StrokeProperty)
                            //    stroke = (Brush)setter.Value;
                        }
                        paletteIndex++;
                        if (paletteIndex >= Palette.Count)
                            paletteIndex = 0;
                    }

                    PropertyInfo piLabel = obj.GetType().GetProperty(Label);
                    PropertyInfo piValue = obj.GetType().GetProperty(Value);
                    string label = piLabel.GetValue(obj, null).ToString();
                    double value = double.Parse(piValue.GetValue(obj, null).ToString());

                    //插入图例
                    Grid gridLegendItem = new Grid { Margin = new Thickness(0, 2, 0, 0) };
                    gridLegendItem.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(20) });
                    gridLegendItem.ColumnDefinitions.Add(new ColumnDefinition());
                    Rectangle rectLengendItem = new Rectangle { Fill = fill, Width = 12, Height = 12, VerticalAlignment = VerticalAlignment.Top, Margin = new Thickness(0, 2, 0, 0) };
                    TextBlock tbLengendItem = new TextBlock { TextWrapping = TextWrapping.Wrap };
                    
                    //设置图例说明
                    tbLengendItem.Text = label;

                    Grid.SetColumn(tbLengendItem, 1);
                    gridLegendItem.Children.Add(rectLengendItem);
                    gridLegendItem.Children.Add(tbLengendItem);
                    spLegend.Children.Add(gridLegendItem);

                    //当前角度
                    double cAngle = value * 360 / sum + startAngle;
                    Point curPoint = startPoint;

                    //计算坐标
                    curPoint.X = centerPoint.X + (chartWidth / 2) * Math.Cos((cAngle - 90) * Math.PI / 180);
                    curPoint.Y = centerPoint.Y + (chartWidth / 2) * Math.Sin((cAngle - 90) * Math.PI / 180);

                    //插入块
                    Path path = new Path();
                    path.Style = style;
                    //path.Fill = fill;
                    //path.Stroke = stroke;
                    path.StrokeThickness = 1;

                    PathFigure pathFigure = new PathFigure { IsClosed = true };
                    pathFigure.StartPoint = centerPoint;
                    LineSegment line = new LineSegment();
                    line.Point = startPoint;
                    pathFigure.Segments.Add(line);
					
					//饼图的圆弧
                    ArcSegment arc = new ArcSegment();
                    arc.Size = new Size(chartWidth / 2, chartWidth / 2);
                    arc.Point = curPoint;
                    arc.SweepDirection = SweepDirection.Clockwise;
                    pathFigure.Segments.Add(arc);

                    PathGeometry pathGeometry = new PathGeometry();
                    pathGeometry.Figures.Add(pathFigure);

                    path.Data = pathGeometry;
                    gChart.Children.Add(path);

                    _List.Add(path);
                    path.Tag = obj;
                    
                    //饼图标识显示
                    if (ShowLabel)
                    {
                        //计算中间角度
                        double mAngle = value * 180 / sum + startAngle;

                        //计算Label坐标
                        double lX = centerPoint.X + (chartWidth / 2) * Math.Cos((mAngle - 90) * Math.PI / 180);
                        double lY = centerPoint.Y + (chartWidth / 2) * Math.Sin((mAngle - 90) * Math.PI / 180);


                        //饼图注记显示
                        TextBlock tbLabel = new TextBlock { TextWrapping = TextWrapping.Wrap, TextAlignment = TextAlignment.Center };

                        //tbLabel.Text = label + "\r\n" + (string.IsNullOrEmpty(this.ValueFormat) ? value.ToString() : value.ToString(this.ValueFormat));
                        //设置为只显示值
                        //tbLabel.Text = value.ToString();
                        //设置为显示名称和值
                        tbLabel.Text = label + "\r\n" + string.Format("{0:#%}", value / sum);
                        
                        if (mAngle <= 90)
                        {
                            tbLabel.HorizontalAlignment = HorizontalAlignment.Left;
                            tbLabel.VerticalAlignment = VerticalAlignment.Bottom;
                            tbLabel.Margin = new Thickness(lX + LabelSpace, 0, 0, this.ActualHeight - lY + LabelSpace);
                        }
                        else
                        {
                            if (mAngle <= 180)
                            {
                                tbLabel.HorizontalAlignment = HorizontalAlignment.Left;
                                tbLabel.VerticalAlignment = VerticalAlignment.Top;
                                tbLabel.Margin = new Thickness(lX + LabelSpace, lY + LabelSpace, 0, 0);
                            }
                            else
                            {
                                if (mAngle <= 270)
                                {
                                    tbLabel.HorizontalAlignment = HorizontalAlignment.Right;
                                    tbLabel.VerticalAlignment = VerticalAlignment.Top;
                                    tbLabel.Margin = new Thickness(0, lY + LabelSpace, this.ActualWidth - (ShowLegend ? LegendWidth : 0) - lX + LabelSpace, 0);
                                }
                                else
                                {
                                    tbLabel.HorizontalAlignment = HorizontalAlignment.Right;
                                    tbLabel.VerticalAlignment = VerticalAlignment.Bottom;
                                    tbLabel.Margin = new Thickness(0, 0, this.ActualWidth - (ShowLegend ? LegendWidth : 0) - lX + LabelSpace, this.ActualHeight - lY + LabelSpace);
                                }
                            }
                        }

                        gChart.Children.Add(tbLabel);
                    }
                    startPoint = curPoint;
                    startAngle = cAngle;
                }
            }
        }
        #endregion
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值