【Telerik控件学习】-建立自己的图形编辑工具(Diagram)

简介: Telerik提供了RadDiagram控件,用于图形元素的旋转,拖拽和缩放.更重要的是,它还拓展了许多绑定的命令(复制,剪切,粘贴,回退等等). 我们可以用来组织自己的图形编辑工具. Step1.

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);
            }
        }
    }
View Code

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"); }
        }
    }
View Code

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"); }
        }
    }
View Code

Step4.定义图形元素的样式

    <!--线路样式-->
    <DataTemplate DataType="{x:Type svgFigs:LineFig}" >
        <Path x:Name="path" StrokeThickness="2" 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="20" Height="20" Fill="Transparent" StrokeThickness="3"/>
        <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>
View Code

Step5.界面编辑工具面板

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

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>    
View Code

Step7.增加图形元素到面板

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

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

 


 

 

文章作者:原子蛋
文章出处:https://www.cnblogs.com/lizzie-xhu/
个人网站:https://www.lancel0t.cn/
个人博客:https://blog.lancel0t.cn/
微信公众号:原子蛋Live+
扫一扫左侧的二维码(或者长按识别二维码),关注本人微信公共号,获取更多资源。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

目录
相关文章
|
传感器
SFNC —— 采集控制(四)(中)
SFNC —— 采集控制(四)
543 4
|
人工智能 API 决策智能
智胜未来:国内大模型+Agent应用案例精选,以及主流Agent框架开源项目推荐
【7月更文挑战第8天】智胜未来:国内大模型+Agent应用案例精选,以及主流Agent框架开源项目推荐
16594 134
智胜未来:国内大模型+Agent应用案例精选,以及主流Agent框架开源项目推荐
|
Ubuntu 网络安全 数据安全/隐私保护
使用WinSCP工具,将windows文件传输到虚拟机Ubuntu系统
使用WinSCP工具,将windows文件传输到虚拟机Ubuntu系统
2524 4
|
测试技术 API 开发者
.NET单元测试框架大比拼:MSTest、xUnit与NUnit的实战较量与选择指南
【8月更文挑战第28天】单元测试是软件开发中不可或缺的一环,它能够确保代码的质量和稳定性。在.NET生态系统中,MSTest、xUnit和NUnit是最为流行的单元测试框架。本文将对这三种测试框架进行全面解析,并通过示例代码展示它们的基本用法和特点。
1552 8
|
算法 Python
群智能算法:【WOA】鲸鱼优化算法详细解读
本文详细解读了鲸鱼优化算法(WOA),这是一种受鲸鱼捕食行为启发的新兴群体智能优化算法,具有强大的全局搜索能力和快速收敛速度。文章分为五个部分,分别介绍了引言、算法原理、主要步骤、特点及Python代码实现。通过模拟鲸鱼的捕食行为,该算法能够在复杂的优化问题中找到全局最优解。
|
数据采集 网络架构
LabVIEW控制DO通道输出一个精确定时的数字波形
LabVIEW控制DO通道输出一个精确定时的数字波形
256 4
|
关系型数据库 MySQL 数据库
如何正确的把Mysql迁移至其他机器上运行
如何正确的把Mysql迁移至其他机器上运行
179 0
|
存储 自然语言处理 数据挖掘
【BERT-多标签文本分类实战】之三——多标签文本分类的方向与常用数据集介绍
【BERT-多标签文本分类实战】之三——多标签文本分类的方向与常用数据集介绍
1328 0
|
C语言
C语言练习之用函数完成数组元素的逆置
C语言练习之用函数完成数组元素的逆置
314 0
|
机器学习/深度学习 Kubernetes 算法
玩转Kubeflow第一章: kubeflow 国内本地安装及案例介绍
kubeflow 是 google 开源的一个基于 kubernetes 的 ML workflow 平台,其集成了大量的机器学习工具,这里给大家介绍下基于阿里云镜像仓库进行kubeflow安装部署,同时通过 kittab 超参数案例,pipeline workflow 的例子给大家详细介绍kubeflow各组件的玩法,同时在最后提出针对kubeflow 构建 MLOps 平台的一些思考。
19422 2
玩转Kubeflow第一章: kubeflow 国内本地安装及案例介绍