用Wpf做一个Block编程画板(续5-Diagram画板)
先上一张效果动图,本次更新主要仿照Scratch,目前仅完成拖拽部分,逻辑部分后续完善。
同样老规矩,先上源码地址:https://gitee.com/akwkevin/aistudio.-wpf.-diagram
本次扩展主要内容:
1.Block模块,入口在文件新建下。
2.简易Block的使用:
3.仿Scratch的Block的使用(完成图鉴,准备编写逻辑):
核心逻辑在源码的BlockDesignerItemViewModelHelper中:
public static void FinishNearBlock(this IBlockDiagramViewModel diagramViewModel, List<BlockDesignerItemViewModel> blocks)
{
if (diagramViewModel == null)
return;
if (blocks.Any())
{
var links = BlockDesignerItemTempLink.Build(blocks);
blocks.ToList().ForEach(p => {
p.ZIndex = diagramViewModel.Items.Where(q => q.ZIndex != int.MaxValue).Any() ? diagramViewModel.Items.Where(q => q.ZIndex != int.MaxValue).Max(r => r.ZIndex) + 1 : 0;
});
foreach (BlockDesignerItemTempLink item in links)
{
var container = diagramViewModel.FindNearContainerToAttachTo(item);
if (container != null)
{
int index = 0;
var child = container.Children.FirstOrDefault(p => p.Connectors.Any(q => q.BeAttachTo == true));
if (child != null)
{
index = container.Children.IndexOf(child);
if (child.RightConnector?.BeAttachTo == true || child.BottomConnector?.BeAttachTo == true)
{
index++;
}
}
diagramViewModel.InsertChildCommand.Execute(new BlockContainerPara() { Item = container.DataItem, Child = item.Items.FirstOrDefault(), Container = container, Index = index });
continue;
}
var portTuple = diagramViewModel.FindNearPortToAttachTo(item);
var portParent = portTuple.Item1;
var portNext = portTuple.Item2;
if (portParent != null)
{
diagramViewModel.AddNextCommand.Execute(new BlockNextPara() { Item = portParent.DataItem as BlockDesignerItemViewModel, Next = item.Items.FirstOrDefault() });
portParent.BeAttachTo = false;
portParent.DisableAttachTo = false;
}
else
{
if (item.Items.FirstOrDefault().Parent != null)
{
diagramViewModel.RemoveNextCommand.Execute(new BlockNextPara() { Item = item.Items.FirstOrDefault().Parent as BlockDesignerItemViewModel, Next = (item.Items.FirstOrDefault().Parent as BlockDesignerItemViewModel)?.Next });
}
}
if (portNext != null)
{
diagramViewModel.AddNextCommand.Execute(new BlockNextPara() { Item = item.Items.LastOrDefault(), Next = portNext.DataItem as BlockDesignerItemViewModel });
portNext.BeAttachTo = false;
portNext.DisableAttachTo = false;
}
else
{
if (item.Items.LastOrDefault().Next != null)
{
diagramViewModel.RemoveNextCommand.Execute(new BlockNextPara() { Item = item.Items.LastOrDefault(), Next = item.Items.LastOrDefault()?.Next });
}
}
}
diagramViewModel.ClearAttachTo();
}
}
大致原理是:判断Block是否被拖入某个容器,如果没有,是否挨着另外一个Block块。