首先说说今天的控件能干什么?1,仿淘宝的评论星级控件,鼠标滑过星星,会变亮。
2,可以用来,展示某一类对象的状态,或者统计信息,比如说,某一类对象,有1~10不同的状态,10为满状态,那么该控件就能根据该对象的状态显示。
显示方法(状态为1的 亮一颗星,灰色的9颗星,状态为2的 亮2颗,灰色的8颗,以此类推)
该控件的属性
<my:StarsControl Number="6" Stars="{Binding Num}" IsComment="True" Margin="5" ClickMe="StarsControl_ClickMe" MoveMe="StarsControl_MoveMe" ></my:StarsControl>
1,Number,要显示的总星数量,比如6,总共显示6颗星(如果用作评论星级,代表满级6星)
2,Stars,该对象的状态,也就是将会亮多少颗星,其他的星(灰色)
3,IsComment,表示该控件是否能鼠标滑过,更改星的状态。true表示更改,false表示只用来展示,不更改
事件
ClickMe,相当于每颗星星的点击事件
MoveMe,相当于每颗星星鼠标移动事件
StarsControl的XAML
<UserControl x:Class="TestDemo.StarsControl" 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" mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="300"> <!--将每个StankPanel做为容器,将星星添加进来--> <StackPanel Orientation="Horizontal" x:Name="item" Loaded="item_Loaded" > </StackPanel> </UserControl>后置代码.cs
public partial class StarsControl : UserControl//评论星级,或显示信誉度 { public StarsControl() { InitializeComponent(); } //定义要显示的星星个数,默认5 public static readonly DependencyProperty NumberProperty = DependencyProperty.Register("Number", typeof(int), typeof(StarsControl), new PropertyMetadata(5,new PropertyChangedCallback(NumberPropertyChanged))); public int Number { get { return (int)GetValue(NumberProperty); } set { SetValue(NumberProperty, value); } } public static void NumberPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { StarsControl starts = (StarsControl)obj; starts.Number = (int)args.NewValue; } //定义是用来显示用户信誉度,还是评星级的 public static readonly DependencyProperty IsCommentProperty = DependencyProperty.Register("IsComment", typeof(bool), typeof(StarsControl), new PropertyMetadata(true, new PropertyChangedCallback(IsCommentPropertyChanged))); public bool IsComment { get { return (bool)GetValue(IsCommentProperty); } set { SetValue(IsCommentProperty, value); } } public static void IsCommentPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { StarsControl starts = (StarsControl)obj; starts.IsComment = (bool)args.NewValue; } //该用户信誉度,总的信誉度是Number,默认亮4颗 public static readonly DependencyProperty StarsProperty = DependencyProperty.Register("Stars", typeof(int), typeof(StarsControl), new PropertyMetadata(new PropertyChangedCallback(StarsPropertyChanged))); public int Stars { get { return (int)GetValue(StarsProperty); } set { SetValue(StarsProperty, value); } } public static void StarsPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { StarsControl test = (StarsControl)obj; string img = "/TestDemo;component/images/1.png";//亮的星星图片 string img1 = "/TestDemo;component/images/0.png";//不亮的星星图片 if ((int)args.NewValue >= test.Number)//判断该用户是的应该亮多少颗星 { for (int i = 0; i < test.Number; i++) { test.item.Children.Add(new Image() { Source = new BitmapImage(new Uri(img, UriKind.RelativeOrAbsolute)), Cursor = Cursors.Hand, ToolTip = new ToolTip() { Content = i + 1 } }); } } else { int num = test.Number - (int)args.NewValue; //该用户没有达到满信誉,则算出不亮的星星有几颗 int i; for (i = 0; i < (int)args.NewValue; i++) { test.item.Children.Add(new Image() { Source = new BitmapImage(new Uri(img, UriKind.RelativeOrAbsolute)), Cursor = Cursors.Hand,ToolTip = new ToolTip() { Content=i+1 }}); } for (int j = 0; j < num; j++) //将不亮的星星加入StankPanel { test.item.Children.Add(new Image() { Source = new BitmapImage(new Uri(img1, UriKind.RelativeOrAbsolute)), Cursor = Cursors.Hand, ToolTip = new ToolTip() { Content=i+j+1 } }); } } } public Point InP; public Point OutP; private void item_Loaded(object sender, RoutedEventArgs e) { foreach (var v in ((StackPanel)sender).Children)//给所有的星星注册事件MouseMove,MouseLeave,MouseEnter { ((Image)v).MouseMove += new MouseEventHandler(StarsControl_MouseMove); ((Image)v).MouseLeave += new MouseEventHandler(StarsControl_MouseLeave); ((Image)v).MouseEnter += new MouseEventHandler(StarsControl_MouseEnter); ((Image)v).MouseLeftButtonDown += new MouseButtonEventHandler(StarsControl_MouseLeftButtonDown);//给每个星星注册一个MouseLeftButtonDown事件 } } public delegate void Click(object sender, MouseButtonEventArgs e); public event Click ClickMe; //定义ClickMe事件,在调用此控件时,可以用该事件操作单个星星 void StarsControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { ClickMe(sender, e); } int result = 0;//记录鼠标是不是第一进入控件 void StarsControl_MouseEnter(object sender, MouseEventArgs e) { if (result == 0)// { InP.X = e.GetPosition((Image)sender).X + 10;//第一次,获取当前坐标将x+10 } else { InP = e.GetPosition((Image)sender);//不是第一次 则就获取当前坐标 result = 1; } } void StarsControl_MouseLeave(object sender, MouseEventArgs e) { if (result == 0) { OutP.X = e.GetPosition((Image)sender).X -10;//第一次,获取当前坐标将x-10 } else { OutP = e.GetPosition((Image)sender);//不是第一次 则就获取当前坐标 result = 1; }; } public delegate void Move(object sender, MouseEventArgs e); public event Move MoveMe; //定义移动事件(调用该控件,如果要在鼠标移动到每个星上更改对象的时候用) //为什么第一次进去和离开要加10和减10,是因为如果一开始 将鼠标移到最后一颗星上,在下面的判断中是相当的,就不会产生变化 void StarsControl_MouseMove(object sender, MouseEventArgs e) { MoveMe(sender, e); if (((bool)GetValue(IsCommentProperty))==true)//如果是用作评论星级的 { string img = "/TestDemo;component/images/1.png"; string img1 = "/TestDemo;component/images/0.png"; if (InP.X < OutP.X) //如果鼠标进入时的坐标小于出去时的坐标,就以为着鼠标在从左向右移动,将所有移过的星星变亮(加载亮星星的路径) { ((Image)sender).Source = new BitmapImage(new Uri(img, UriKind.RelativeOrAbsolute)); } else { //从右向左在移动,星星变灰 ((Image)sender).Source = new BitmapImage(new Uri(img1, UriKind.RelativeOrAbsolute)); } //第一颗星星永远亮着 ((Image)item.Children[0]).Source = new BitmapImage(new Uri(img, UriKind.RelativeOrAbsolute)); } } }
以上StarsControl控件已经Ok,下面调用xaml
<StackPanel Name="stackPanel1" > <ItemsControl x:Name="Item"> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15"> <ItemsPresenter/> </Border> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" > <TextBlock Text="{Binding Name}" Margin="10"></TextBlock> <my:StarsControl x:Name="starts" Number="6" Stars="{Binding Num}" IsComment="True" Margin="5" ClickMe="StarsControl_ClickMe" MoveMe="StarsControl_MoveMe" ></my:StarsControl> <TextBlock Text="信誉度" Margin="10"></TextBlock> <TextBlock Text="{Binding Num}" Margin="10"></TextBlock> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel>
后置代码绑定public class person { private string name; public string Name { get { return name; } set { name = value; } } private int num; public int Num { get { return num; } set { num = value; } } }List<person> list = new List<person>(); list.Add(new person() { Name = "Jack", Num = 2 }); list.Add(new person() { Name = "Jack", Num = 3 }); list.Add(new person() { Name = "Jack", Num = 4 }); list.Add(new person() { Name = "Jack", Num = 5 }); list.Add(new person() { Name = "Jack", Num = 6 }); list.Add(new person() { Name = "Jack", Num = 7 }); Item.ItemsSource = list;
我是做了一个多条数据的绑定,当然可以直接赋值<my:StarsControl x:Name="starts" Number="6" Stars="5" IsComment="True" Margin="5" ></my:StarsControl>
好了,看看效果总共显示6颗星,对象的状态为2,3,4,5,6,7 和直接赋值的5,星都是可以更改的 因为IsComment为True嘛,
还有两个事件
private void StarsControl_ClickMe(object sender, MouseButtonEventArgs e) { MessageBox.Show(((person)((Image)sender).DataContext).Name); } private void StarsControl_MoveMe(object sender, MouseEventArgs e) { MessageBox.Show(((person)((Image)sender).DataContext).Name); }加载没错,jack的Num是2,3,4,5,6,7,
上下两张图片的星是不是不一样了,这就是IsComment属性为True 从左向右滑过灰色图片变亮,从右向左滑过时,变灰的效果
这个是ClickMe事件,点击星星时,弹出当前对象的名字
在看IsComment设为false,只展示不能改变星星的状态
我鼠标在6的位置 星星没有变亮...
还有个定义事件应该判断
public delegate void Click(object sender, MouseButtonEventArgs e); public event Click ClickMe; //定义ClickMe事件,在调用此控件时,可以用该事件操作单个星星 void StarsControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (ClickMe != null) { ClickMe(sender, e); } }MoveMe也一样..............
昨天本来做了一个动画的按钮,有点丑,放上去,又删掉了.....周末了,大家周末玩的开心..............................................