微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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" 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",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),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),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),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));
                //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)) });
                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) };
                    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,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,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);
                            }
                            else
                            {
                                if (mAngle <= 270)
                                {
                                    tbLabel.HorizontalAlignment = HorizontalAlignment.Right;
                                    tbLabel.VerticalAlignment = VerticalAlignment.Top;
                                    tbLabel.Margin = new Thickness(0,this.ActualWidth - (ShowLegend ? LegendWidth : 0) - lX + LabelSpace,0);
                                }
                                else
                                {
                                    tbLabel.HorizontalAlignment = HorizontalAlignment.Right;
                                    tbLabel.VerticalAlignment = VerticalAlignment.Bottom;
                                    tbLabel.Margin = new Thickness(0,this.ActualHeight - lY + LabelSpace);
                                }
                            }
                        }

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐