WPF在Gmap.net中将Marker动起来
出处来源于博客园 作者张子浩 原文地址https://www.cnblogs.com/zaranet/p/12766143.html,如有转载,请联系我,如无经过作者同意,作者有权申请法律保护。
前一段时间说过一篇绘制极坐标的,这段时间对它进行了改造已经今非昔比了,功能实现了很多,我目的是让marker动起来,然后还会绘制route,上篇也就是简单的绘制了route,没有关于marker的相关知识。
那个circle有一定的改造,原来的纯色改成了渐变,这个你可以提前想好,不过在代码中你要做好适配,将 system.draw.color 转换成了 media.color ,取其中的argb值。
public circle(string name, int radius,string[] vs) { radius = radius; m_viewmodelcircle = new viewmodelcircle(); m_viewmodelcircle.circledis = name; this.datacontext = m_viewmodelcircle; initializecomponent(); //控制circle radialgradientbrush radialgradient = new radialgradientbrush(); var obj = colortranslator.fromhtml(vs[0]); var ob2 = colortranslator.fromhtml(vs[1]); var ob3 = colortranslator.fromhtml(vs[2]); this.circle.stroke= new solidcolorbrush(system.windows.media.color.fromargb(ob3.a, ob3.r, ob3.g, ob3.b)); radialgradient.gradientstops.add(new gradientstop(system.windows.media.color.fromargb(obj.a, obj.r, obj.g, obj.b), 0.75)); radialgradient.gradientstops.add(new gradientstop(system.windows.media.color.fromargb(ob2.a, ob2.r, ob2.g, ob2.b), 1)); this.circle.fill = radialgradient; }
我们都知道在wpf的gmap.net中没有了gmapoverlay 概念,所有的东西都在marker中操作,这样其实有一个优点,就是把overlay和marker混合在一起更好管理,你可以通过tag来寻找你对象,非常轻便,但设计者不是这么认为的,可能是某些原理没法走通。
最基本的右击在map中添加标点可以这么操作。
private void radarmap_mouserightbuttonup(object sender, mousebuttoneventargs e) { point clickpoint = e.getposition(radarmap); pointlatlng point = radarmap.fromlocaltolatlng((int)clickpoint.x, (int)clickpoint.y); id += 1; gmapmarker currentmarker = new gmapmarker(point); { currentmarker.shape = new custommarker(id, currentmarker); //(currentmarker.shape as custommarker).setcontent(point, "1"); 这种方法可以触发setcontent currentmarker.zindex = -1; currentmarker.position = point; radarmap.markers.add(currentmarker); this.focus(); } }
代码中可以发现我们可以轻松将gmap的marker shape属性 ,随后转换成原来的marker类型,轻松调用属于它的方法,所以它的生命周期是等待它所在gmap中的marker被销毁才会被dispose,至于我的标点数据是从那里接受的,我只是启用两个demo而已,发了个udp通讯,一般来说都是使用结构体来接受,传入的byte值,我们进行逆转。
public static object bytestostruct(byte[] buf, int len, type type) { // int len = marshal.sizeof(buf); object rtn; intptr buffer = marshal.allochglobal(len); marshal.copy(buf, 0, buffer, len); rtn = marshal.ptrtostructure(buffer, type); marshal.freehglobal(buffer); return rtn; }
下面的代码是关于绘制,以及判断marker是否存在,如果存在则修改postion,而且还要重新绘制route,每个route是对应着它的marker,所以需要一个字典,每次重新绘制的时候,先将route全部删除,随后重新所有的点,然后进行绘制route,这个代码可能性能上有缺陷,但也是没有办法。
list<radartargetinfo> dislist = new list<radartargetinfo>(); //已经添加的集合 public list<radartargetinfo> addlist = new list<radartargetinfo>(); //用于画线 dictionary<string,list<pointlatlng>> pointlatlngsdic = new dictionary<string,list<pointlatlng>>(); //标点和数据id的关系 list<markerdatarole> rolelist = new list<markerdatarole>(); /// <summary> /// 检查数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void checkdata(object sender, eventargs e) { if (currentmarkercontext.list.count == 0) { return; } //应该添加的数据 var list = currentmarkercontext.list.except(addlist).tolist(); addlist.addrange(list); dislist.clear(); foreach (var group in list.groupby(u => u.id)) { int flyid = group.key; radartargetinfo radartarget = new radartargetinfo(); pointlatlng currentpoint = new pointlatlng(); foreach (var item in group) { pointlatlng point = new pointlatlng(item.latitude, item.longitude); currentpoint = point; //代表没有 if (rolelist.firstordefault(u => u.dataid == flyid) == null) { gmapmarker currentmarker = new gmapmarker(point); { currentmarker.shape = new custommarker(flyid, currentmarker); currentmarker.zindex = -1; currentmarker.tag = flyid; currentmarker.position = point; radarmap.markers.add(currentmarker); } rolelist.add(new markerdatarole(){dataid = flyid,markerid = flyid}); } else { radarmap.markers.where(u => u.tag != null).where(u => convert.toint32(u.tag) == flyid).firstordefault().position = point; } var str = flyid.tostring(); if (pointlatlngsdic.containskey(str)) { pointlatlngsdic[str].add(point); } else { var value = new list<pointlatlng>(); value.add(point); pointlatlngsdic.add(str, value); } radartarget = item; } dislist.add(radartarget); //这里找到flyid (radarmap.markers.where(u => convert.toint32(u.tag) == flyid).firstordefault().shape as custommarker).setcontent(currentpoint, flyid); } this.雷达目标数据.itemssource = dislist; foreach (var item in radarmap.markers.where(u => u.tag != null).where(u => u.tag.tostring() == "line").tolist()) { radarmap.markers.remove(item); } foreach (var item in pointlatlngsdic) { gmaproute gmroute = new gmaproute(pointlatlngsdic[item.key]) { shape = new line() { strokethickness = 4 },tag = "line" }; radarmap.markers.add(gmroute); } }
还有一个需要强调的是,上面说过可以通过shape找到本身调用其方法,那个marker上面的文本就是这么改的。
public void setcontent(pointlatlng point, int pihao) { this.批号.content = pihao.tostring(); this.纬度.content = "纬度:" + ((int)(point.lat * 1000) / 1000.0).tostring(); this.经度.content = "纬度:" + ((int)(point.lng * 1000) / 1000.0).tostring(); }
(radarmap.markers.where(u => convert.toint32(u.tag) == flyid).firstordefault().shape as custommarker).setcontent(currentpoint, flyid);
还有就是至于我的wpf程序自适应问题,我都是用viewbox做的,因为前端ui他老是玩margin,so...你懂的!人家都是blend for visual studio 给搞的。也只能见谅了.