【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+
扫一扫左侧的二维码(或者长按识别二维码),关注本人微信公共号,获取更多资源。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

目录
相关文章
|
C# 前端开发
WPF - 图形设计器(Diagram Designer)
原文:WPF - 图形设计器(Diagram Designer)   OpenExpressApp计划中包括建模工具,计划是采用MetaEdit+模型来作为元模型,使用codeproject的《WPF Diagram Designer》一系列文章来做为设计器实现参考,本篇介绍一下codeprojcet的这四个文章,推荐给对图形设计器感兴趣的人去看看,通过WPF的模板功能和其他功能可以很方便的设计出图形编辑器。
3582 0
|
C# 开发者 Windows
WPF技术之图形系列Path控件
WPF Path是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制复杂的几何路径形状。它可以通过设置一系列的路径命令以及相应的参数来定义形状,可以绘制任意复杂度的路径。
1107 0
|
C++
QT图形视图系统 - 使用一个项目来学习QT的图形视图框架 - 始篇
详细的介绍可以看QT的官方助手,那里面介绍的详细且明白,需要一定的英语基础,我这里直接使用一个开源项目来介绍QGraphicsView、QGraphicsScene的使用。
304 1
QT图形视图系统 - 使用一个项目来学习QT的图形视图框架 - 终篇
接上一篇,我们需要继续完成以下的效果; 先上个效果图:
124 0
|
调度 Windows C#
理解 UWP 视图的概念,让 UWP 应用显示多个窗口(多视图)
原文 理解 UWP 视图的概念,让 UWP 应用显示多个窗口(多视图) UWP 应用多是一个窗口完成所有业务的,事实上我也推荐使用这种单一窗口的方式。不过,总有一些特别的情况下我们需要用到不止一个窗口,那么 UWP 中如何使用多窗口呢? 本文内容 为什么 UWP 需要多窗口? UWP 视图的概念 UWP 多窗口 管理多个 UWP 视图 参考资料 为什么 UWP 需要多窗口? 多窗口在传统 Win32 的开发当中是司空见惯的事儿了,不过我个人非常不喜欢,因为 Windows 系统上的多窗口太多坑。
1645 0
|
C#
使用Blend设计出符合效果的WPF界面
原文:使用Blend设计出符合效果的WPF界面 之前不会用blend,感觉好难的,但美工给出的效果自己有没办法实现,所以研究了一下blend,感觉没有想象中的那么难 废话不多说,开始界面设计 今天拿到美工给的一个界面效果图 这个界面说实话,还可以吧,勉强说得过去。
2274 0
|
C#
在WPF设计工具Blend2中制作立方体图片效果
原文:在WPF设计工具Blend2中制作立方体图片效果 --------------------------------------------------------------------------------引用时请保留以下信息:大可山 [MSN:a3news(AT)hotmail.
1070 0