自己画图,灵活性高,事件也自定义
这是画布,其他的自己补:
namespace L.Bussiness.画布图元s { public class CanvasForPrimitives : Canvas, IPrimitiveContainer { public CanvasForPrimitives CurrentRootCanvas { get; set; } public bool IsRoot => ReferenceEquals(this, CurrentRootCanvas); public PropertyGridEx PropertyGrid { get; private set; } public CanvasForPrimitives() { PropertyGrid = MainWindow.PropertyGrid; CurrentRootCanvas = this; AllowDrop = true; ClipToBounds = true; Focusable = true; Scale = 1d; this.LayoutTransform = _scaleTransform; if (IsRoot) { WidthEx = 800; HeightEx = 600; } } [Filed] [Category("1.基本属性")] [DisplayName("宽度")] [Description("尺寸.")] public virtual double WidthEx { get => base.Width; set => base.Width = value < MinWidth ? base.Width : value; } [Filed] [Category("1.基本属性")] [DisplayName("高度")] [Description("尺寸.")] public virtual double HeightEx { get => base.Height; set => base.Height = value < MinHeight ? base.Height : value; } private readonly ScaleTransform _scaleTransform = new ScaleTransform(); public double Scale { get => _scaleTransform.ScaleX; set { if(value<0d)return; var minDistance = Math.Min(ActualHeight, ActualWidth) * value; if(minDistance < 40 || value>50d)return; _scaleTransform.ScaleX = _scaleTransform.ScaleY = value; _scaleTransform.CenterX = ActualWidth / 2; _scaleTransform.CenterY = ActualHeight / 2; LayoutTransform = _scaleTransform; } } public double ScaleTick { get; set; } = 0.05d; protected override void OnMouseWheel(MouseWheelEventArgs e) { base.OnMouseWheel(e); if (Keyboard.IsKeyDown(Key.LeftCtrl)) { if (!IsRoot) return; if (e.Delta < 0) Scale -= ScaleTick; else Scale += ScaleTick; } } [Filed] public virtual IList Primitives { get => base.Children; set { if(value == null || value.Count<1) return;//{base.Children.Clear();return;} value.OfType<PrimitiveBase>().ToList().ForEach(t=>InsertPrimitive(t)); } } private PrimitiveBase _primitiveLastSelect;//暂时还没用 /// <summary> /// 除设置Children(反序列化)使用,所有Primitive的添加应该从此处 /// </summary> /// <param name="primitive"></param> /// <param name="index">默认-1添加到尾部</param> public virtual void InsertPrimitive(PrimitiveBase primitive,int index=-1) { if(index<-1 || index>=Primitives.Count)throw new IndexOutOfRangeException("Invalidate index for the Canvas."); if(primitive==null)return; primitive.WhenSelected = sender => { //_primitiveLastSelect?.IsSelected //安全起见,把除自己的状态UnSelected一下,并通知设置面板 this.CurrentRootCanvas.GetAllPrimitives().Where(t => t != sender).ToList().ForEach(t => t.ForceUnselect()); if (CurrentRootCanvas.PropertyGrid != null) CurrentRootCanvas.PropertyGrid.SelectedObject = primitive; _primitiveLastSelect = sender; }; if (index < 0) base.Children.Add(primitive); else base.Children.Insert(index,primitive); //告诉当前节点Canvas是谁,如果当前节点是Container,需要告诉所有子元素Canvas是谁 primitive.CurrentRootCanvas = this; primitive.AsType<PrimitiveAndContainerBasic>()?.GetAllPrimitives().ForEach(t=>t.CurrentRootCanvas = this); } protected override void OnDrop(DragEventArgs e) { base.OnDrop(e); this.DoOnDrop(e); } public string Save(string filePath) { var content = this.ToJsonString(new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, ContractResolver = new LimitPrimitivePropertyContractResolver() }); System.IO.File.WriteAllText(filePath,content); return content; } public static CanvasForPrimitives OpenCreate(string filePath) { try { var content = System.IO.File.ReadAllText(filePath); var bean = content.ToEntityFromJsonString<CanvasForPrimitives>(new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, ContractResolver = new LimitPrimitivePropertyContractResolver() }); ReDoOnCreatedByFile(bean); return bean; } catch (Exception e) { Loger.Log.Error(e); throw e; } } static void ReDoOnCreatedByFile(IPrimitiveContainer primitiveContainer) { var items = primitiveContainer.Primitives.OfType<PrimitiveBase>().ToList(); primitiveContainer.Primitives.Clear(); items.ForEach(t => { primitiveContainer.InsertPrimitive(t); if(t is IPrimitiveContainer) ReDoOnCreatedByFile(t.AsType<IPrimitiveContainer>()); }); } } }