欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

WP7自定义控件 评分控件

程序员文章站 2023-10-31 08:47:28
最近在写一个新的app程序,需要使用评分功能,wp的toolkit里面没有包含,只能自己写一个了。   评分控件要点 评分控件已经很熟悉了,还是总结一下要点。 1. 由10个(可...

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