WPF-22:WPF绘制五角星改进版(增加半个五角星的绘制)

来源:互联网 发布:linux文件权限为400 编辑:程序博客网 时间:2024/04/29 19:55
初步实现了一个绘制五角星的控件(http://blog.csdn.net/yysyangyangyangshan/article/details/9303005),但是在实际中有一种情况显示半颗五角星的。下面做一下改进,完善一下这个五角星控件。
功成名:TestFivePointStarLikeTaobao,
项目如图,

1、两种五角星的绘制方法
这两种计算坐标的方法比较重要。
五点画法,也是常用画法。
        /// <summary>        ///第一种画法 根据半径和圆心确定五个点        /// </summary>        /// <param name="center"></param>        /// <returns></returns>        private PointCollection GetFivePoint1(Point center,double r)        {            double h1 = r * Math.Sin(18 * Math.PI / 180);            double h2 = r * Math.Cos(18 * Math.PI / 180);            double h3 = r * Math.Sin(36 * Math.PI / 180);            double h4 = r * Math.Cos(36 * Math.PI / 180);            Point p1 = new Point(r, center.X);            Point p2 = new Point(r - h2, r - h1);            Point p3 = new Point(r - h3, r + h4);            Point p4 = new Point(r + h3, p3.Y);            Point p5 = new Point(r + h2, p2.Y);            List<Point> values = new List<Point>() { p1, p3, p5, p2, p4 };            PointCollection pcollect = new PointCollection(values);            return pcollect;        }
十点画法,这种比较方便画半颗五角星。
        /// <summary>        ///第二种画法 根据半径和圆心确定十个点        /// </summary>        /// <param name="center"></param>        /// <returns></returns>        private PointCollection GetFivePoint2(Point center, double r)        {            int i;            //两个圆的半径 和第一个点初始角度            //r1 = r / 2.5, r2 = r值的互换确定是正五角星还是倒五角星            double r1 = r / 2.5, r2 = r, g = 18;            double pi = Math.PI;            List<Point> values = new List<Point>(10);//十个点            List<Point> values1 = new List<Point>(5);//(内)外接五个点            List<Point> values2 = new List<Point>(5);//(外)内接五个点            for (i = 0; i < 5; i++)            {                //计算10个点的坐标                Point p1 = new Point(r1 * Math.Cos(g * pi / 180), r1 * Math.Sin(g * pi / 180));                Point p2 = new Point(r2 * Math.Cos((g + 36) * pi / 180), r2 * Math.Sin((g + 36) * pi / 180));                values1.Add(p1);                values2.Add(p2);                g += 72;            }            //左半边:3,4,5,6,7,8            //右半边:1,2,3,8,9,10            values.Add(values1[0]);//1            values.Add(values2[0]);//2            values.Add(values1[1]);//3            values.Add(values2[1]);//4            values.Add(values1[2]);//5            values.Add(values2[2]);//6            values.Add(values1[3]);//7            values.Add(values2[3]);//8            values.Add(values1[4]);//9            values.Add(values2[4]);//10                       PointCollection pcollect = new PointCollection(values);            return pcollect;        }
五角星类代码:
    public class FivePointStar:UserControl    {        private double radius = 20;        private double currentPart = 1;        private Brush selectBackground = new SolidColorBrush(Colors.YellowGreen);        private Brush unselectBackgroud = new SolidColorBrush(Colors.DarkGray);        /// <summary>        /// 半径        /// </summary>        public double Radius        {            get             {               object result = GetValue(RadiusProperty);                if(result==null)                {                    return radius;                }                return (double)result;            }            set            {                SetValue(RadiusProperty, value);                this.InvalidateVisual();            }        }        public static  DependencyProperty RadiusProperty =           DependencyProperty.Register("Radius", typeof(double), typeof(FivePointStar), new UIPropertyMetadata());        /// <summary>        /// 当前是否是一颗星        /// </summary>        public double CurrentPart        {            get            {                object result = GetValue(CurrentPartProperty);                if (result == null)                {                    return currentPart;                }                return (double)result;            }            set            {                SetValue(CurrentPartProperty, value);                this.InvalidateVisual();            }        }        public static  DependencyProperty CurrentPartProperty =           DependencyProperty.Register("CurrentPart", typeof(double), typeof(FivePointStar), new UIPropertyMetadata());        /// <summary>        /// 选中颜色        /// </summary>        public Brush SelectBackground        {            get            {                object result = GetValue(SelectBackgroundProperty);                if (result == null)                {                    return selectBackground;                }                return (Brush)result;            }            set            {                SetValue(SelectBackgroundProperty, value);                //this.InvalidateVisual();            }        }        public static  DependencyProperty SelectBackgroundProperty =           DependencyProperty.Register("SelectBackground", typeof(Brush), typeof(FivePointStar), new UIPropertyMetadata());        /// <summary>        /// 未选中颜色        /// </summary>        public Brush UnSelectBackground        {            get            {                object result = GetValue(UnSelectBackgroundProperty);                if (result == null)                {                    return unselectBackgroud;                }                return (Brush)result;            }            set            {                SetValue(UnSelectBackgroundProperty, value);            }        }        public static  DependencyProperty UnSelectBackgroundProperty =           DependencyProperty.Register("UnSelectBackground", typeof(Brush), typeof(FivePointStar), new UIPropertyMetadata());        public FivePointStar()            : base()        {            this.Loaded += new RoutedEventHandler(FivePointStar_Loaded);        }        void FivePointStar_Loaded(object sender, RoutedEventArgs e)        {            //如果使用第一种画法就要开启此注释            //this.MinHeight = Radius * 2;            //this.MaxHeight = Radius * 2;            //this.MinWidth = Radius * 2;            //this.MaxWidth = Radius * 2;            //this.Background = Brushes.Transparent;            this.MinHeight = 0;            this.MaxHeight = 0;            this.MinWidth = 0;            this.MaxWidth = 0;            this.Background = Brushes.Transparent;        }        protected override void OnRender(System.Windows.Media.DrawingContext dc)        {            base.OnRender(dc);            Point center = new Point();            PointCollection Points = GetFivePoint2(center,Radius);            Canvas ca = new Canvas();            if (CurrentPart == 1)            {                Polygon plg = new Polygon();                plg.Points = Points;                plg.Stroke = Brushes.Transparent;                plg.StrokeThickness = 2;                plg.Fill = this.SelectBackground;                plg.FillRule = FillRule.Nonzero;                ca.Children.Add(plg);            }            else if (CurrentPart ==0)            {                Polygon plg = new Polygon();                plg.Points = Points;                plg.Stroke = Brushes.Transparent;                plg.StrokeThickness = 2;                plg.Fill = this.UnSelectBackground;                plg.FillRule = FillRule.Nonzero;                ca.Children.Add(plg);            }            else            {                //半边五角星的画法                Polygon plg1 = new Polygon();                Polygon plg2 = new Polygon();                plg1.Points = Points;                plg1.Stroke = Brushes.Transparent;                plg1.StrokeThickness = 2;                plg1.FillRule = FillRule.Nonzero;                plg2.Points = Points;                plg2.Stroke = Brushes.Transparent;                plg2.StrokeThickness = 2;                plg2.FillRule = FillRule.Nonzero;                //左半边:3,4,5,6,7,8                //右半边:1,2,3,8,9,10                plg1.Points = new PointCollection()                 {                     Points[2],                    Points[3],                    Points[4],                    Points[5],                    Points[6],                    Points[7],                };                plg1.Fill = SelectBackground;                plg2.Points = new PointCollection()                 {                     Points[0],                    Points[1],                    Points[2],                    Points[7],                    Points[8],                    Points[9],                };                plg2.Fill = UnSelectBackground;                ca.Children.Add(plg1);                ca.Children.Add(plg2);            }            ca.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;            ca.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;            this.Content = ca;            //Brush b = new SolidColorBrush(Colors.Yellow);            //Pen p = new Pen(b, 2);            //var path = new Path();            //var gc = new GeometryConverter();            //path.Data = (Geometry)gc.ConvertFromString(string.Format("M {0} {1} {2} {3} {4} Z",            //    Points[0], Points[1], Points[2], Points[3], Points[4]));            //path.Fill = Brushes.Yellow;            //dc.DrawGeometry(b, p, path.Data);        }        /// <summary>        ///第一种画法 根据半径和圆心确定五个点        /// </summary>        /// <param name="center"></param>        /// <returns></returns>        private PointCollection GetFivePoint1(Point center,double r)        {            double h1 = r * Math.Sin(18 * Math.PI / 180);            double h2 = r * Math.Cos(18 * Math.PI / 180);            double h3 = r * Math.Sin(36 * Math.PI / 180);            double h4 = r * Math.Cos(36 * Math.PI / 180);            Point p1 = new Point(r, center.X);            Point p2 = new Point(r - h2, r - h1);            Point p3 = new Point(r - h3, r + h4);            Point p4 = new Point(r + h3, p3.Y);            Point p5 = new Point(r + h2, p2.Y);            List<Point> values = new List<Point>() { p1, p3, p5, p2, p4 };            PointCollection pcollect = new PointCollection(values);            return pcollect;        }        /// <summary>        ///第二种画法 根据半径和圆心确定十个点        /// </summary>        /// <param name="center"></param>        /// <returns></returns>        private PointCollection GetFivePoint2(Point center, double r)        {            int i;            //两个圆的半径 和第一个点初始角度            //r1 = r / 2.5, r2 = r值的互换确定是正五角星还是倒五角星            double r1 = r / 2.5, r2 = r, g = 18;            double pi = Math.PI;            List<Point> values = new List<Point>(10);//十个点            List<Point> values1 = new List<Point>(5);//(内)外接五个点            List<Point> values2 = new List<Point>(5);//(外)内接五个点            for (i = 0; i < 5; i++)            {                //计算10个点的坐标                Point p1 = new Point(r1 * Math.Cos(g * pi / 180), r1 * Math.Sin(g * pi / 180));                Point p2 = new Point(r2 * Math.Cos((g + 36) * pi / 180), r2 * Math.Sin((g + 36) * pi / 180));                values1.Add(p1);                values2.Add(p2);                g += 72;            }            //左半边:3,4,5,6,7,8            //右半边:1,2,3,8,9,10            values.Add(values1[0]);//1            values.Add(values2[0]);//2            values.Add(values1[1]);//3            values.Add(values2[1]);//4            values.Add(values1[2]);//5            values.Add(values2[2]);//6            values.Add(values1[3]);//7            values.Add(values2[3]);//8            values.Add(values1[4]);//9            values.Add(values2[4]);//10                       PointCollection pcollect = new PointCollection(values);            return pcollect;        }    }
这个可以直接使用,效果如下

2、多颗五角星控件
前台,
<UserControl x:Class="TestFivePointStarLikeTaobao.FivePointStarGroup"             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"              xmlns:local="clr-namespace:TestFivePointStarLikeTaobao"             mc:Ignorable="d">    <Grid x:Name="groupGrid" Background="Transparent">        <ListBox x:Name="lsbchildCategory" ItemsSource="{Binding ChildCategoryList,IsAsync=True}"                     Background="WhiteSmoke" BorderThickness="0">            <ListBox.ItemTemplate>                <DataTemplate>                    <local:FivePointStar Radius="{Binding Radius}" CurrentPart="{Binding CurrentValue}" Tag="{Binding ID}" Margin="{Binding Margins}"                                         SelectBackground="{Binding SelectBackground}" UnSelectBackground="{Binding UnselectBackgroud}"                                         MouseDown="FivePointStar_MouseDown"/>                </DataTemplate>            </ListBox.ItemTemplate>            <ListBox.ItemsPanel>                <ItemsPanelTemplate>                    <StackPanel  VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Center"/>                </ItemsPanelTemplate>            </ListBox.ItemsPanel>        </ListBox>    </Grid></UserControl>
后台,
    /// <summary>    /// FivePointStarGroup.xaml 的交互逻辑    /// </summary>    public partial class FivePointStarGroup : UserControl    {        private double radius = 20;        private double itemsCount = 5;        private double selectCount = 5;        private Brush selectBackground = new SolidColorBrush(Colors.YellowGreen);        private Brush unselectBackgroud = new SolidColorBrush(Colors.DarkGray);          /// <summary>        /// 五角星半径        /// </summary>        public double Radius        {            get             {               object result = GetValue(RadiusProperty);                if(result==null)                {                    return radius;                }                return (double)result;            }            set            {                SetValue(RadiusProperty, value);            }        }        public static  DependencyProperty RadiusProperty =           DependencyProperty.Register("Radius", typeof(double),            typeof(FivePointStarGroup), new UIPropertyMetadata());        /// <summary>        /// 五角星个数        /// </summary>        public double ItemsCount        {            get            {                object result = GetValue(ItemsCountProperty);                if (result == null)                {                    return  itemsCount;                }                return (double)result;            }            set            {                SetValue(ItemsCountProperty, value);                InitialData();                this.InvalidateVisual();            }        }        public static  DependencyProperty ItemsCountProperty =           DependencyProperty.Register("ItemsCount", typeof(double),           typeof(FivePointStar), new UIPropertyMetadata());        /// <summary>        /// 选中的五角星个数        /// </summary>        public double SelectCount        {            get            {                object result = GetValue(SelectCountProperty);                if (result == null)                {                    return selectCount;                }                return (double)result;            }            set            {                SetValue(SelectCountProperty, value);                InitialData();                this.InvalidateVisual();            }        }        public static  DependencyProperty SelectCountProperty =           DependencyProperty.Register("SelectCount", typeof(double),           typeof(FivePointStar), new UIPropertyMetadata());        public event RoutedEventHandler SelectCountChangeEvent        {            add { AddHandler(SelectCountChangePropertyEvent, value); }            remove { RemoveHandler(SelectCountChangePropertyEvent, value); }        }        /// <summary>        /// 选中颜色        /// </summary>        public Brush SelectBackground        {            get            {                object result = GetValue(SelectBackgroundProperty);                if (result == null)                {                    return selectBackground;                }                return (Brush)result;            }            set            {                SetValue(SelectBackgroundProperty, value);            }        }        public static  DependencyProperty SelectBackgroundProperty =           DependencyProperty.Register("SelectBackground", typeof(Brush),           typeof(FivePointStarGroup), new UIPropertyMetadata());        /// <summary>        /// 未选中颜色        /// </summary>        public Brush UnSelectBackground        {            get            {                object result = GetValue(UnSelectBackgroundProperty);                if (result == null)                {                    return unselectBackgroud;                }                return (Brush)result;            }            set            {                SetValue(UnSelectBackgroundProperty, value);            }        }        public static  DependencyProperty UnSelectBackgroundProperty =           DependencyProperty.Register("UnSelectBackground", typeof(Brush),            typeof(FivePointStarGroup), new UIPropertyMetadata());        public static  RoutedEvent SelectCountChangePropertyEvent =             EventManager.RegisterRoutedEvent("SelectCountChangeEvent",              RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Control));        public FivePointStarGroup()        {            InitializeComponent();            this.Loaded += new RoutedEventHandler(FivePointStarGroup_Loaded);        }        void FivePointStarGroup_Loaded(object sender, RoutedEventArgs e)        {            InitialData();        }        private void InitialData()        {            List<FivePointStarModel> list = new List<FivePointStarModel>();            int count = Convert.ToInt32(this.ItemsCount);            if (count <= 0)            {                count = Convert.ToInt32(this.itemsCount);            }            for (int i = 0; i < count; i++)            {                FivePointStarModel item = new FivePointStarModel();                item.ID = i + 1;                item.Radius = Radius;                item.SelectBackground = SelectBackground;                item.UnselectBackgroud = UnSelectBackground;                item.Margins = new Thickness(Radius, 0, Radius, 0);                //在此设置星形显示的颜色                if ((i + 1) > SelectCount && ((i + 1 - SelectCount) > 0) &&                     (i + 1 - SelectCount) < 1)                {                    item.CurrentValue = 0.5;                }                else if ((i + 1) > SelectCount)                {                    item.CurrentValue = 0;                }                else                {                    item.CurrentValue = 1;                }                list.Add(item);            }            this.lsbchildCategory.ItemsSource = list;        }        private void FivePointStar_MouseDown(object sender, MouseButtonEventArgs e)        {            FivePointStar m = sender as FivePointStar;            if (m == null)            {                return;            }            int index = Convert.ToInt32(m.Tag);            this.SelectCount = index;            RaiseEvent(new RoutedEventArgs(SelectCountChangePropertyEvent, sender));         }    }
用于绑定的类,
   public class FivePointStarModel:NotifyObject    {        private int id;        private double radius = 20;        private double currentValue = 1;        private Brush selectBackground = new SolidColorBrush(Colors.GreenYellow);        private Brush unselectBackgroud = new SolidColorBrush(Colors.DarkGray);        private Thickness margins = new Thickness(0);        public int ID        {            get { return id; }            set            {                id = value;                this.OnPropertyChanged("Radius");            }        }        public double Radius        {            get { return radius; }            set             {                 radius = value;                this.OnPropertyChanged("Radius");            }        }        public double CurrentValue        {            get { return currentValue; }            set             {                currentValue = value;                this.OnPropertyChanged("CurrentValue");            }        }        public Brush SelectBackground        {            get { return selectBackground; }            set            {                selectBackground = value;                this.OnPropertyChanged("SelectBackground");            }        }        public Brush UnselectBackgroud        {            get { return unselectBackgroud; }            set            {                unselectBackgroud = value;                this.OnPropertyChanged("UnselectBackgroud");            }        }        public Thickness Margins        {            get { return margins; }            set            {                margins = value;                this.OnPropertyChanged("Radius");            }        }    }    public abstract class NotifyObject : INotifyPropertyChanged    {        public void OnPropertyChanged(string propname)        {            if (this.PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs(propname));            }        }        public event PropertyChangedEventHandler PropertyChanged;    }
这个控件中,增加了设置一颗五角星的三种状态:全选中、全部选中,选中半颗。
对于绑定的类,增加了Margin的绑定。
3、测试调用
前台,
<Window x:Class="TestFivePointStarLikeTaobao.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        Title="MainWindow" Height="446" Width="849" xmlns:my="clr-namespace:TestFivePointStarLikeTaobao">    <Grid>        <my:FivePointStarGroup HorizontalAlignment="Stretch" Margin="136,65,361,281" x:Name="fivePointStarGroup1"                                VerticalAlignment="Stretch" SelectBackground="GreenYellow" Radius="30" Visibility="Visible"                               UnSelectBackground="DarkGray" ItemsCount="5" SelectCount="5" />        <TextBox Height="30" HorizontalAlignment="Left" Margin="202,232,0,0" Name="textBox1" VerticalAlignment="Top" Width="120"  FontSize="18" />        <Button Content="设 置" Height="46" HorizontalAlignment="Left" Margin="365,192,0,0" Name="button1" VerticalAlignment="Top" Width="142" FontSize="18" Click="button1_Click" />        <TextBox Height="30" HorizontalAlignment="Left" Margin="202,159,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" FontSize="18"/>        <TextBlock Height="23" HorizontalAlignment="Left" Margin="136,232,0,0" Name="textBlock1" Text="选 中:" VerticalAlignment="Top" FontSize="18"/>        <TextBlock Height="23" HorizontalAlignment="Left" Margin="136,159,0,0" Name="textBlock2" Text="总 数:" VerticalAlignment="Top"  FontSize="18"/>        <my:FivePointStar HorizontalAlignment="Left" Margin="666,232,0,0" x:Name="fivePointStar1" VerticalAlignment="Top" Height="0" Width="0" Radius="30"                          CurrentPart="1"/>    </Grid></Window>
后台,
    /// <summary>    /// MainWindow.xaml 的交互逻辑    /// </summary>    public partial class MainWindow : Window    {        public MainWindow()        {            InitializeComponent();            InitialData();            this.fivePointStarGroup1.SelectCountChangeEvent += new RoutedEventHandler(fivePointStarGroup1_SelectCountChangeEvent);        }        private void InitialData()        {            this.textBox1.Text = this.fivePointStarGroup1.SelectCount.ToString();            this.textBox2.Text = this.fivePointStarGroup1.ItemsCount.ToString();        }        void fivePointStarGroup1_SelectCountChangeEvent(object sender, RoutedEventArgs e)        {            InitialData();        }        private void button1_Click(object sender, RoutedEventArgs e)        {            double selectCount = Convert.ToDouble(this.textBox1.Text);            int allCount = Convert.ToInt32(this.textBox2.Text);            if (allCount < selectCount)            {                MessageBox.Show("参数设置错误!");                return;            }            this.fivePointStarGroup1.ItemsCount = allCount;            this.fivePointStarGroup1.SelectCount = selectCount;        }    } 
最终效果图,

这样可以适用于大部分的评级功能。
代码下载:http://download.csdn.net/detail/yysyangyangyangshan/5743911

原创粉丝点击