类似淘宝的评级控件在程序业务中使用比较多,尤其是对于电子商务方面的编程。最近做了这样的一个小功能,使用WPF实现。但是对于五角星的绘制部分的代码(包括计算五个点),可以应用于Winform,ASP.NET等。下面来看代码的实现。
该项目名称:TestFivePointStarLikeTaobao。这个项目如下图,
1、五角星的绘制。
绘制五角星,主要是要根据半径获得五个点。
2、绘制一组五角星。
WPF代码,
界面代码:
调用:
代码下载:
http://download.youkuaiyun.com/detail/yysyangyangyangshan/5738491
该项目名称:TestFivePointStarLikeTaobao。这个项目如下图,
1、五角星的绘制。
绘制五角星,主要是要根据半径获得五个点。
/// <summary> /// 根据半径和圆心确定五个点 /// </summary> /// <param name="center"></param> /// <returns></returns> private PointCollection GetFivePoint(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; }
WPF这个类如下,
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); } } 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; } protected override void OnRender(System.Windows.Media.DrawingContext dc) { base.OnRender(dc); Point center = new Point(); PointCollection Points = GetFivePoint(center); Canvas ca = new Canvas(); Polygon plg = new Polygon(); plg.Points = Points; plg.Stroke = Brushes.Transparent; plg.StrokeThickness = 2; if (CurrentPart == 1) { plg.Fill = this.SelectBackground; } else { plg.Fill = this.UnSelectBackground; } plg.FillRule = FillRule.Nonzero; ca.Children.Add(plg); 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 GetFivePoint(Point center) { double r = Radius; 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; } }
可以直接将该类作为自定义控件放置于容器控件上。效果如下,
2、绘制一组五角星。
WPF代码,
界面代码:
<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}" 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; //在此设置星形显示的颜色 if ((i+1) > SelectCount) { item.CurrentValue = 0; } 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: INotifyPropertyChanged { public void OnPropertyChanged(string name) { if (this.PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } public event PropertyChangedEventHandler PropertyChanged; 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); 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"); } } }
上面就是五角星和多个五角星的全部代码。
调用:
<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="62,27,59,254" x:Name="fivePointStarGroup1" VerticalAlignment="Stretch" SelectBackground="GreenYellow" Radius="30" 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="576,240,0,0" x:Name="fivePointStar1" VerticalAlignment="Top" Height="20" Width="154" Radius="20" 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) { int selectCount = Convert.ToInt32(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.youkuaiyun.com/detail/yysyangyangyangshan/5738491