当前位置: 移动技术网 > IT编程>移动开发>WP > WP7自定义控件 评分控件

WP7自定义控件 评分控件

2018年09月13日  | 移动技术网IT编程  | 我要评论

最近在写一个新的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
 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网