Telerik提供了RadDiagram控件,用于图形元素的旋转,拖拽和缩放.更重要的是,它还拓展了许多绑定的命令(复制,剪切,粘贴,回退等等).

我们可以用来组织自己的图形编辑工具.

Step1.定义图形元素容器(Shape)的基类,继承RadDiagramShape,并重写Serialize和Deserialize方法,来定制将来对象的保存或复制.

    /// <summary>
/// 图形Shape控件
/// </summary>
public class FigureShape : RadDiagramShape
{
public FigureShape()
{
IsConnectorsManipulationEnabled = false;
}
/// <summary>
/// 序列化
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 反序列化
/// </summary>
/// <param name="serializationInfo"></param>
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.定义图形元素基类,并支持可序列化

    /// <summary>
/// 图形基类
/// </summary>
[Serializable]
public abstract class FigureBase : NotificationObject
{
/// <summary>
/// 图形位置
/// </summary>
private Point position;
public Point Position
{
get { return position; }
set { position = value; RaisePropertyChanged("Position"); }
}
}

Step3.定义基本图形元素,继承FigureBase,只列出一个示例,不再详述

    [Serializable]
public class StationFig : FigureBase
{
/// <summary>
/// xml节点构造
/// </summary>
/// <param name="node"></param>
public StationFig(XmlNode node)
{
var infoNode = node.ChildNodes.Cast<XmlNode>().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");
} /// <summary>
/// 厂站类型(220kv,500kv)
/// </summary>
private string stationType;
public string StationType
{
get { return stationType; }
set { stationType = value; RaisePropertyChanged("StationType"); }
}
}

Step4.定义图形元素的样式

    <!--线路样式-->
<DataTemplate DataType="{x:Type svgFigs:LineFig}" >
<Path x:Name="path" StrokeThickness="" Data="{Binding Path}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding LineType}" Value="kv500">
<Setter Property="Stroke" Value="Yellow" TargetName="path"/>
</DataTrigger>
<DataTrigger Binding="{Binding LineType}" Value="kv220">
<Setter Property="Stroke" Value="White" TargetName="path"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<!--厂站样式-->
<DataTemplate DataType="{x:Type svgFigs:StationFig}" >
<Ellipse x:Name="ellipse" Width="" Height="" Fill="Transparent" StrokeThickness=""/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding StationType}" Value="kv500">
<Setter Property="Stroke" Value="Yellow" TargetName="ellipse"/>
</DataTrigger>
<DataTrigger Binding="{Binding StationType}" Value="kv220">
<Setter Property="Stroke" Value="White" TargetName="ellipse"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<!--文本样式-->
<DataTemplate DataType="{x:Type svgFigs:TextFig}" >
<TextBlock x:Name="text" Foreground="White" FontFamily="{Binding FontFamily}" FontSize="{Binding FontSize}" Text="{Binding Text}"/>
</DataTemplate>

Step5.界面编辑工具面板

<telerik:RadDiagram x:Name="diagram"  MinWidth="" BorderThickness=""
Background="Black"
IsBackgroundSurfaceVisible="False"
IsSnapToItemsEnabled="False"
IsSnapToGridEnabled="False"/>

Step6.关键步骤,定义Shape容器中ContentTemplate显示内容

<Style TargetType="{x:Type common:FigureShape}">
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Position" Value="{Binding Position,Mode=TwoWay}"/>
<Setter Property="Content" Value="{Binding}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type common:FigureShape}">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Step7.增加图形元素到面板

        /// <summary>
/// 增加图元到绘图面板
/// </summary>
/// <param name="figure"></param>
private void AddFigureToDiagram(FigureBase figure)
{
var shape = new FigureShape() { DataContext = figure };
diagram.AddShape(shape);
}

编辑工具示例:(支持图元的旋转,移动,缩放,复制粘贴等操作,属性编辑,缩略图导航...)

【Telerik控件学习】-建立自己的图形编辑工具(Diagram)的更多相关文章

  1. 【Telerik控件学习】-制作3D效果的柱状图(ChartView)

    首先,定义柱状图,并设置自定义的DataTemplate <telerik:RadCartesianChart > <telerik:RadCartesianChart.Horizo ...

  2. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  3. DevExpress控件学习总结(转)

    DevExpress控件学习总结   1.Navigation & Layout 1.1 Bar Manager 如果想在窗体或用户控件(user control)上添加工具条(bars)或弹 ...

  4. Android Material Design控件学习(三)——使用TextInputLayout实现酷市场登录效果

    前言 前两次,我们学习了 Android Material Design控件学习(一)--TabLayout的用法 Android Material Design控件学习(二)--Navigation ...

  5. WinFrom 第三方控件 TeleRik控件

    1.首先从工具-拓展与应用中下载安装  TeleRik WinFroms VsExtensions   TeleRik dll文件     2.工具箱控件  将Telerik控件更新过来 3.新建一个 ...

  6. wxPython控件学习之wx.grid.Grid 表格控件

    wxPython控件学习之wx.grid.Grid (包括对GridCellEditor和GridCelRender的扩展,以支持更多的grid cell 样式, 以GridCellColorEdit ...

  7. 转)delphi chrome cef3 控件学习笔记 (二)

    (转)delphi chrome cef3 控件学习笔记 (二) https://blog.csdn.net/risesoft2012/article/details/51260832 原创 2016 ...

  8. PyQt5Day03--程序基本结构之面向对象版本+控件学习

    1.程序基本结构之面向对象版本 (1)开发阶段(自己写好并测试)——设置为模版qto from PyQt5.Qt import * class Window(QWidget): def __init_ ...

  9. DevExpress控件学习总结 z

    1.Navigation & Layout 1.1 Bar Manager 如果想在窗体或用户控件(user control)上添加工具条(bars)或弹出菜单(popup menus),我们 ...

随机推荐

  1. JSP第七篇【简单标签、应用、DynamicAttribute接口】

    为什么要用到简单标签? 上一篇博客中我已经讲解了传统标签,想要开发自定义标签,大多数情况下都要重写doStartTag(),doAfterBody()和doEndTag()方法,并且还要知道SKIP_ ...

  2. Eclipse读取含有extjs的项目文件时卡死或者编写ExtJS时卡

    新建一个Eclipse或MyEclipse项目时,关掉验证. 项目右键-->Properties-->Builders--> 不勾选(JavaScript Validator.Val ...

  3. 快速学会require的使用

    快速学会使用require.js 1.get start 先到官网下载requirejs到本地,官方同时提供Node版本r.js,我们只使用requirejs即可. 接下来在页面上写入 <scr ...

  4. 认识StringBuffer类

    概述: StringBuffer类是线程安全的可变字符序列 线程安全效率低 StringBuffer和String的区别 * String是一个不可变的字符序列 * StringBuffer是一个可变 ...

  5. 【转】开源中国上看到的一个vim的自动配置的好东西,分享下

    https://www.oschina.net/p/onekey-to-vim-ide 变量有高亮,竖行上有直线定位,对python的支持效果更佳,从事C/C++开发的程序员使用也不错.

  6. oracle pl/sql 分页

    一.无返回值的存储过程 古人云:欲速则不达,为了让大家伙比较容易接受分页过程编写,我还是从简单到复杂,循序渐进的给大家讲解.首先是掌握最简单的存储过程,无返回值的存储过程. 案例:现有一张表book, ...

  7. MySQL高级查询(一)

    修改表 修改表名 语法: ALTER  TABLE<旧表名> RENAME  [TO] <新表名>; 添加字段 语法: ALTER  TABLE 表名 ADD 字段名 数据类型 ...

  8. springmvc返回枚举属性值

    使用fastJSON ,在枚举中写toString 方法 如下@Overridepublic String toString() {return "{" + this.name() ...

  9. Ngnix技术研究系列2-基于Redis实现动态路由

    上篇博文我们写了个引子: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 发现了新大陆,OpenResty OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台 ...

  10. Football 概率DP poj3071

                                                                                                 Footbal ...