欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > 内容正文

WP7自定义控件 评分控件

来源: 开发者 投稿于  被查看 10554 次 评论:22

WP7自定义控件 评分控件


最近在写一个新的APP程序,需要使用评分功能,WP的Toolkit里面没有包含,只能自己写一个了。
 
评分控件要点
评分控件已经很熟悉了,还是总结一下要点。
1. 由10个(可配置)横排的五星组成,默认非高亮色(灰色)
2. 得分由从左到右高亮(如红色,颜色可配置)显示得分数量的五星,控件能够提供获取和设置得分的属性。
3. 可以点击其中一个五星修改评分。
4. 为了提高触摸体验,支持拖动控件修改得分
 
根据要点设计控件
根据要点1设计控件布局
Horizontal排列的StackPanel(包含在ItemsControl 控件内部) 和 绘制五星的Path 组成。
最上面提供一个透明的Rectangle扩展触摸空间(WP只能在绘制的控件上触摸)。
<ItemsControl x:Name="stars">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal" />
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Path Data="M16,0 L19.77688,12.223213 L32.000001,12.222913 L22.111121,19.776973 L25.888544,32.000001 L16,24.445454 L6.1114563,32.000001 L9.88888,19.776973 L2.2971745E-08,12.222913 L12.22312,12.223213 z"
                              Fill="{Binding Fill}" HorizontalAlignment="Left" Height="32" Margin="1,0" Width="32"
                              Stretch="Fill" VerticalAlignment="Top" />
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                        <Rectangle Fill="#00000000"/>


根据要点1、2设计控件属性
Brush MarkedFill  选中了的五星刷子
Brush UnMarkedFill 未选中的五星刷子
int MaxStars 最大五星数量
Marked 当前评价值
 
根据要点2设计控件属性改变行为
很简单获取Marked 然后将每个五星都修改一下颜色
private void FillStars(int index)
        {
            if (!VerifyValue(index)) return;

            for (int i = 0, length = starItems.Count; i < length; i++)
            {
                var star = starItems[i];
                if (i > index)
                {
                    star.Fill = UnMarkedFill;
                }
                else
                {
                    star.Fill = MarkedFill;
                }
            }

        }


根据要点3、4设计控件触控行为
将2个要点合并了,实现方法为:
• 滑动前(点中): 修改为当前X轴的高亮位置
• 滑动中:根据X轴变化高亮位置
• 滑动完成(放开): 修改为当前X轴的高亮位置,并更新评分Marked 当前评价值
通过五星的宽度可以获取X轴所在的五星
代码如下:
protected override void OnManipulationStarted(ManipulationStartedEventArgs e)
        {
            e.Handled = true;
            UpdateStar(e.ManipulationOrigin);
            base.OnManipulationStarted(e);
        }

        protected override void OnManipulationDelta(ManipulationDeltaEventArgs e)
        {
            e.Handled = true;
            UpdateStar(e.ManipulationOrigin);
            base.OnManipulationDelta(e);
        }

        protected override void OnManipulationCompleted(ManipulationCompletedEventArgs e)
        {
            e.Handled = true;
            var index = UpdateStar(e.ManipulationOrigin);
            if (VerifyValue(index)) { Marked = index + 1; }
            base.OnManipulationCompleted(e);
        }

 
完整代码
 
  View Code
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace KimiStudio.Controls
{
    public class StarMark : Control
    {
        private ItemsControl stars;
        private const int StarSize = 34;
        private ObservableCollection<StarItem> starItems;

        #region DependencyPropertys
        public static readonly DependencyProperty MarkedFillProperty =
           DependencyProperty.Register("MarkedFill", typeof(Brush), typeof(StarMark),
           new PropertyMetadata(new SolidColorBrush(Colors.Red)));

        public static readonly DependencyProperty UnMarkedFillProperty =
            DependencyProperty.Register("UnMarkedFill", typeof(Brush), typeof(StarMark),
            new PropertyMetadata(new SolidColorBrush(Colors.DarkGray)));

        public static readonly DependencyProperty MaxStarsProperty =
            DependencyProperty.Register("MaxStars", typeof(int), typeof(StarMark),
            new PropertyMetadata(10));

        public static readonly DependencyProperty MarkedProperty =
            DependencyProperty.Register("Marked", typeof(int), typeof(StarMark),
            new PropertyMetadata(0, OnMarkedPropertyChanged));

        public int Marked
        {
            get { return (int)GetValue(MarkedProperty); }
            set { SetValue(MarkedProperty, value); }
        }

        public int MaxStars
        {
            get { return (int)GetValue(MaxStarsProperty); }
            set { SetValue(MaxStarsProperty, value); }
        }

        public Brush UnMarkedFill
        {
            get { return (Brush)GetValue(UnMarkedFillProperty); }
            set { SetValue(UnMarkedFillProperty, value); }
        }

        public Brush MarkedFill
        {
            get { return (Brush)GetValue(MarkedFillProperty); }
            set { SetValue(MarkedFillProperty, value); }
        }

        private static void OnMarkedPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args)
        {
            var starMark = o as StarMark;
            if (starMark == null || args.NewValue == args.OldValue) return;

            starMark.SetMarked((int)args.NewValue);
        }

        #endregion

        public StarMark()
        {
            this.DefaultStyleKey = typeof(StarMark);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            stars = (ItemsControl)GetTemplateChild("stars");

            starItems = new ObservableCollection<StarItem>();
            for (int i = 0, length = MaxStars; i < length; i++)
            {
                starItems.Add(new StarItem { Fill = UnMarkedFill });
            }
            stars.ItemsSource = starItems;
            SetMarked(Marked);
        }

        private void SetMarked(int value)
        {
            if (stars == null) return; ;
            FillStars(value - 1);
        }

        protected override void OnManipulationStarted(ManipulationStartedEventArgs e)
        {
            e.Handled = true;
            UpdateStar(e.ManipulationOrigin);
            base.OnManipulationStarted(e);
        }

        protected override void OnManipulationDelta(ManipulationDeltaEventArgs e)
        {
            e.Handled = true;
            UpdateStar(e.ManipulationOrigin);
            base.OnManipulationDelta(e);
        }

        protected override void OnManipulationCompleted(ManipulationCompletedEventArgs e)
        {
            e.Handled = true;
            var index = UpdateStar(e.ManipulationOrigin);
            if (VerifyValue(index)) { Marked = index + 1; }
            base.OnManipulationCompleted(e);
        }

        private int UpdateStar(Point point)
        {
            int x = (int)point.X;
            int index = x / StarSize;
            FillStars(index);
            return index;
        }
       
        //SL可用
        //protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        //{
        //    int x = (int)e.GetPosition(stars).X;
        //    int index = x / StarSize;
        //    FillStars(index);

        //    if (VerifyValue(index)) { Marked = index + 1; }
        //    base.OnMouseLeftButtonUp(e);
        //}

    
        private bool VerifyValue(int index)
        {
            if (index < 0 || index >= stars.Items.Count) return false;
            return true;
        }

        private void FillStars(int index)
        {
            if (!VerifyValue(index)) return;

            for (int i = 0, length = starItems.Count; i < length; i++)
            {
                var star = starItems[i];
                if (i > index)
                {
                    star.Fill = UnMarkedFill;
                }
                else
                {
                    star.Fill = MarkedFill;
                }
            }

        }

 

        public class StarItem : INotifyPropertyChanged
        {
            private Brush fill;

            public event PropertyChangedEventHandler PropertyChanged;

            public Brush Fill
            {
                get { return fill; }
                set
                {
                    if (fill == value) return;
                    fill = value;
                    OnPropertyChanged("Fill");
                }
            }

            private void OnPropertyChanged(string propertyName)
            {
                var handler = PropertyChanged;
                if (handler == null) return;
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

对应的Generic.xaml
  View Code
 <Style TargetType="local:StarMark">
        <Setter Property="Width" Value="340"/>
        <Setter Property="Height" Value="35"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:StarMark">
                    <Grid>
                        <ItemsControl x:Name="stars">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal" />
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Path Data="M16,0 L19.77688,12.223213 L32.000001,12.222913 L22.111121,19.776973 L25.888544,32.000001 L16,24.445454 L6.1114563,32.000001 L9.88888,19.776973 L2.2971745E-08,12.222913 L12.22312,12.223213 z"
                              Fill="{Binding Fill}" HorizontalAlignment="Left" Height="32" Margin="1,0" Width="32"
                              Stretch="Fill" VerticalAlignment="Top" />
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                        <Rectangle Fill="#00000000"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


 摘自  kiminozo
 

相关文章

    暂无相关文章
相关频道:

用户评论