Telerik提供了RadDiagram控件,用于图形元素的旋转,拖拽和缩放.更重要的是,它还拓展了许多绑定的命令(复制,剪切,粘贴,回退等等).
我们可以用来组织自己的图形编辑工具.
Step1.定义图形元素容器(Shape)的基类,继承RadDiagramShape,并重写Serialize和Deserialize方法,来定制将来对象的保存或复制.
////// 图形Shape控件 /// public class FigureShape : RadDiagramShape { public FigureShape() { IsConnectorsManipulationEnabled = false; } ////// 序列化 /// ///public override SerializationInfo Serialize() { SerializationInfo serializationInfo = base.Serialize(); try { var obj = base.Content as FigureBase; if (obj != null) { IFormatter formatter = new BinaryFormatter(); using (var ms = new MemoryStream()) { formatter.Serialize(ms, obj); serializationInfo["Figure"] = Convert.ToBase64String(ms.ToArray()); } } } catch (Exception e) { throw new Exception("序列化过程失败:" + e.Message); } return serializationInfo; } /// /// 反序列化 /// /// public override void Deserialize(SerializationInfo serializationInfo) { base.Deserialize(serializationInfo); try { if (serializationInfo["Figure"] != null) { var buffer = Convert.FromBase64String(serializationInfo["Figure"].ToString()); IFormatter formatter = new BinaryFormatter(); using (var ms = new MemoryStream(buffer)) { Content = formatter.Deserialize(ms); //绑定Shape坐标和Figure坐标 this.DataContext = Content; var binding = new Binding("Position") { Mode = BindingMode.TwoWay }; this.SetBinding(PositionProperty, binding); } } } catch (Exception e) { throw new Exception("反序列化过程失败:" + e.Message); } } }
Step2.定义图形元素基类,并支持可序列化
////// 图形基类 /// [Serializable] public abstract class FigureBase : NotificationObject { ////// 图形位置 /// private Point position; public Point Position { get { return position; } set { position = value; RaisePropertyChanged("Position"); } } }
Step3.定义基本图形元素,继承FigureBase,只列出一个示例,不再详述
[Serializable] public class StationFig : FigureBase { ////// xml节点构造 /// /// public StationFig(XmlNode node) { var infoNode = node.ChildNodes.Cast().FirstOrDefault(s => s.Name == "use"); var xAttri = infoNode.GetAttributeByName("x"); var yAttri = infoNode.GetAttributeByName("y"); this.Position = new Point(double.Parse(xAttri), double.Parse(yAttri)); this.StationType = infoNode.GetAttributeByName("class"); } /// /// 厂站类型(220kv,500kv) /// private string stationType; public string StationType { get { return stationType; } set { stationType = value; RaisePropertyChanged("StationType"); } } }
Step4.定义图形元素的样式
Step5.界面编辑工具面板
Step6.关键步骤,定义Shape容器中ContentTemplate显示内容
Step7.增加图形元素到面板
////// 增加图元到绘图面板 /// /// private void AddFigureToDiagram(FigureBase figure) { var shape = new FigureShape() { DataContext = figure }; diagram.AddShape(shape); }
编辑工具示例:(支持图元的旋转,移动,缩放,复制粘贴等操作,属性编辑,缩略图导航...)