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
上一篇: Linux seq命令的使用方法
下一篇: 瞅见这些逗B老师就笑想