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

初步实现了一个绘制五角星的控件(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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值