This commit is contained in:
kwai
2023-06-16 19:03:15 +08:00
parent 1dd09a2240
commit 56c3aac8e8
12 changed files with 167 additions and 102 deletions

View File

@@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@@ -10,15 +12,15 @@ using AIStudio.Wpf.DiagramDesigner.Helpers;
namespace AIStudio.Wpf.DiagramDesigner namespace AIStudio.Wpf.DiagramDesigner
{ {
public class ItemsContainer : ContentControl public class BlockItemsContainer : ContentControl
{ {
static ItemsContainer() static BlockItemsContainer()
{ {
DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsContainer), new FrameworkPropertyMetadata(typeof(ItemsContainer))); DefaultStyleKeyProperty.OverrideMetadata(typeof(BlockItemsContainer), new FrameworkPropertyMetadata(typeof(BlockItemsContainer)));
} }
public static readonly DependencyProperty BorderProperty = DependencyProperty.Register( public static readonly DependencyProperty BorderProperty = DependencyProperty.Register(
nameof(Border), typeof(object), typeof(ItemsContainer), new PropertyMetadata(default(object))); nameof(Border), typeof(object), typeof(BlockItemsContainer), new PropertyMetadata(default(object)));
public object Border public object Border
{ {
@@ -27,7 +29,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
public static readonly DependencyProperty BorderTemplateProperty = DependencyProperty.Register( public static readonly DependencyProperty BorderTemplateProperty = DependencyProperty.Register(
nameof(BorderTemplate), typeof(DataTemplate), typeof(ItemsContainer), new PropertyMetadata(default(DataTemplate))); nameof(BorderTemplate), typeof(DataTemplate), typeof(BlockItemsContainer), new PropertyMetadata(default(DataTemplate)));
[Bindable(true), Category("Content")] [Bindable(true), Category("Content")]
public DataTemplate BorderTemplate public DataTemplate BorderTemplate
@@ -37,7 +39,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
public static readonly DependencyProperty BorderTemplateSelectorProperty = DependencyProperty.Register( public static readonly DependencyProperty BorderTemplateSelectorProperty = DependencyProperty.Register(
nameof(BorderTemplateSelector), typeof(DataTemplateSelector), typeof(ItemsContainer), new PropertyMetadata(default(DataTemplateSelector))); nameof(BorderTemplateSelector), typeof(DataTemplateSelector), typeof(BlockItemsContainer), new PropertyMetadata(default(DataTemplateSelector)));
[Bindable(true), Category("Content")] [Bindable(true), Category("Content")]
public DataTemplateSelector BorderTemplateSelector public DataTemplateSelector BorderTemplateSelector
@@ -47,7 +49,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
public static readonly DependencyProperty BorderStringFormatProperty = DependencyProperty.Register( public static readonly DependencyProperty BorderStringFormatProperty = DependencyProperty.Register(
nameof(BorderStringFormat), typeof(string), typeof(ItemsContainer), new PropertyMetadata(default(string))); nameof(BorderStringFormat), typeof(string), typeof(BlockItemsContainer), new PropertyMetadata(default(string)));
[Bindable(true), Category("Content")] [Bindable(true), Category("Content")]
public string BorderStringFormat public string BorderStringFormat
@@ -58,7 +60,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public static readonly DependencyProperty ParentPanelProperty = public static readonly DependencyProperty ParentPanelProperty =
DependencyProperty.Register(nameof(ParentPanel), typeof(FrameworkElement), typeof(ItemsContainer), DependencyProperty.Register(nameof(ParentPanel), typeof(FrameworkElement), typeof(BlockItemsContainer),
new FrameworkPropertyMetadata(null)); new FrameworkPropertyMetadata(null));
public FrameworkElement ParentPanel public FrameworkElement ParentPanel
@@ -76,7 +78,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public static readonly DependencyProperty GetOffSetFuncProperty = public static readonly DependencyProperty GetOffSetFuncProperty =
DependencyProperty.Register(nameof(GetOffSetFunc), DependencyProperty.Register(nameof(GetOffSetFunc),
typeof(Func<Point>), typeof(Func<Point>),
typeof(ItemsContainer), typeof(BlockItemsContainer),
new FrameworkPropertyMetadata(null)); new FrameworkPropertyMetadata(null));
public Func<Point> GetOffSetFunc public Func<Point> GetOffSetFunc
{ {
@@ -98,14 +100,14 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
public ItemsContainerInfo Info public BlockItemsContainerInfo Info
{ {
get get
{ {
if (Border is ItemsContainerInfo itemsContainerInfo) if (Border is BlockItemsContainerInfo itemsContainerInfo)
return itemsContainerInfo; return itemsContainerInfo;
return this.DataContext as ItemsContainerInfo; return this.DataContext as BlockItemsContainerInfo;
} }
} }
@@ -119,11 +121,18 @@ namespace AIStudio.Wpf.DiagramDesigner
get; private set; get; private set;
} }
public ItemsContainer() public Point? FirstPoint
{
get; private set;
}
public BlockItemsContainer()
{ {
} }
public static List<BlockItemsContainer> Containers = new List<BlockItemsContainer>();
public override void OnApplyTemplate() public override void OnApplyTemplate()
{ {
base.OnApplyTemplate(); base.OnApplyTemplate();
@@ -131,33 +140,31 @@ namespace AIStudio.Wpf.DiagramDesigner
GetOffSetFunc = GetOffSet; GetOffSetFunc = GetOffSet;
} }
Point? firstPoint;
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{ {
base.OnMouseLeftButtonDown(e); base.OnMouseLeftButtonDown(e);
firstPoint = e.GetPosition(this); FirstPoint = e.GetPosition(this);
Containers.Add(this);
} }
protected override void OnMouseMove(MouseEventArgs e) protected override void OnMouseMove(MouseEventArgs e)
{ {
base.OnMouseMove(e); base.OnMouseMove(e);
if (firstPoint != null) if (FirstPoint != null)
{ {
var currentPoint = e.GetPosition(this); var currentPoint = e.GetPosition(this);
if (Math.Sqrt(Math.Pow(firstPoint.Value.X - currentPoint.X, 2) + Math.Pow(firstPoint.Value.Y - currentPoint.Y, 2)) > 5) if (Math.Sqrt(Math.Pow(FirstPoint.Value.X - currentPoint.X, 2) + Math.Pow(FirstPoint.Value.Y - currentPoint.Y, 2)) > 5)
{ {
firstPoint = null; FirstPoint = null;
if (Info?.Children?.Count > 0) if (Info?.Children?.Count > 0)
{ {
var borders = VisualHelper.FindVisualChildren<BlockBorder>(this); var borders = VisualHelper.FindVisualChildren<BlockBorder>(this);
BlockBorder innerblock = null;
BlockDesignerItemViewModel dragObject = null;
Point dragOffset = new Point();
foreach (var border in borders) foreach (var border in borders)
{ {
var itemsContainer = VisualHelper.TryFindParent<ItemsContainer>(border); var itemsContainers = VisualHelper.TryFindParent<BlockItemsContainer>(border);
if (this != itemsContainer) if (this != itemsContainers)
{ {
continue; continue;
} }
@@ -174,6 +181,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (DragObject != null) if (DragObject != null)
{ {
Containers.ForEach(p => p.FirstPoint = null);
DesignerCanvas canvas = GetDesignerCanvas(this); DesignerCanvas canvas = GetDesignerCanvas(this);
if (canvas != null) if (canvas != null)
{ {
@@ -189,7 +197,9 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
base.OnMouseUp(e); base.OnMouseUp(e);
firstPoint = null; FirstPoint = null;
Containers.Clear();
} }
public ConnectorOrientation Orientation public ConnectorOrientation Orientation

View File

@@ -0,0 +1,23 @@
<ItemsControl x:Class="AIStudio.Wpf.DiagramDesigner.BlockItemsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AIStudio.Wpf.DiagramDesigner"
xmlns:dd="clr-namespace:AIStudio.Wpf.DiagramDesigner"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<dd:BlockBorder>
<ContentControl Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</dd:BlockBorder>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace AIStudio.Wpf.DiagramDesigner
{
/// <summary>
/// BlockItemsControl.xaml 的交互逻辑
/// </summary>
public partial class BlockItemsControl : ItemsControl
{
public BlockItemsControl()
{
InitializeComponent();
}
protected override System.Windows.DependencyObject GetContainerForItemOverride()
{
return new ListBoxItem();
}
}
}

View File

@@ -84,8 +84,8 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
private ItemsContainer _sourceItemsContainer; private BlockItemsContainer _sourceItemsContainer;
public ItemsContainer SourceItemsContainer public BlockItemsContainer SourceItemsContainer
{ {
get get
{ {
@@ -98,7 +98,7 @@ namespace AIStudio.Wpf.DiagramDesigner
_sourceItemsContainer = value; _sourceItemsContainer = value;
if (_sourceItemsContainer != null) if (_sourceItemsContainer != null)
{ {
ItemsContainerInfo sourceDataItem = _sourceItemsContainer.Info; BlockItemsContainerInfo sourceDataItem = _sourceItemsContainer.Info;
sourceDataItem.DataItem.RemoveChild(_sourceItemsContainer.DragObject); sourceDataItem.DataItem.RemoveChild(_sourceItemsContainer.DragObject);

View File

@@ -158,7 +158,7 @@
</DataTemplate.Triggers> </DataTemplate.Triggers>
</DataTemplate> </DataTemplate>
<DataTemplate DataType="{x:Type dd:ItemsContainerInfo}"> <DataTemplate DataType="{x:Type dd:BlockItemsContainerInfo}">
<Grid dd:WidthAndHeightProps.Active="True" <Grid dd:WidthAndHeightProps.Active="True"
dd:WidthAndHeightProps.BoundActualWidth="{Binding ActualItemWidth,Mode=OneWayToSource}" dd:WidthAndHeightProps.BoundActualWidth="{Binding ActualItemWidth,Mode=OneWayToSource}"
dd:WidthAndHeightProps.BoundActualHeight="{Binding ActualItemHeight,Mode=OneWayToSource}"> dd:WidthAndHeightProps.BoundActualHeight="{Binding ActualItemHeight,Mode=OneWayToSource}">
@@ -181,10 +181,10 @@
</DataTemplate> </DataTemplate>
<!-- DragThumb Default Template --> <!-- DragThumb Default Template -->
<Style TargetType="{x:Type dd:ItemsContainer}"> <Style TargetType="{x:Type dd:BlockItemsContainer}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type dd:ItemsContainer}"> <ControlTemplate TargetType="{x:Type dd:BlockItemsContainer}">
<Border Background="{TemplateBinding Background}" <Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"

View File

@@ -99,65 +99,64 @@
</DataTemplate> </DataTemplate>
<DataTemplate DataType="{x:Type dd:BlockDesignerItemViewModel}"> <DataTemplate DataType="{x:Type dd:BlockDesignerItemViewModel}">
<dd:BlockBorder> <Grid x:Name="grid" MinWidth="{Binding MinItemWidth}" MinHeight="{Binding MinItemHeight}">
<Grid x:Name="grid" MinWidth="{Binding MinItemWidth}" MinHeight="{Binding MinItemHeight}"> <Grid IsHitTestVisible="False">
<Grid IsHitTestVisible="False"> <Rectangle StrokeThickness="1" Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" />
<Rectangle StrokeThickness="1" Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" /> <Border x:Name="left" HorizontalAlignment="Left" Width="5" Background="Transparent"/>
<Border x:Name="left" HorizontalAlignment="Left" Width="5" Background="Transparent"/> <Control x:Name="PART_Text" IsHitTestVisible="{Binding IsReadOnlyText,Converter={StaticResource InvertBoolConverter}}">
<Control x:Name="PART_Text" IsHitTestVisible="{Binding IsReadOnlyText,Converter={StaticResource InvertBoolConverter}}"> <Control.Style>
<Control.Style> <Style TargetType="Control">
<Style TargetType="Control"> <Setter Property="Template">
<Setter Property="Template"> <Setter.Value>
<Setter.Value> <ControlTemplate>
<ControlTemplate> <Grid/>
<Grid/> </ControlTemplate>
</ControlTemplate> </Setter.Value>
</Setter.Value> </Setter>
</Setter> <Style.Triggers>
<Style.Triggers> <DataTrigger Binding="{Binding ShowText}" Value="True">
<DataTrigger Binding="{Binding ShowText}" Value="True"> <Setter Property="Template">
<Setter Property="Template"> <Setter.Value>
<Setter.Value> <ControlTemplate>
<ControlTemplate> <dd:TextControl x:Name="PART_Text" />
<dd:TextControl x:Name="PART_Text" /> </ControlTemplate>
</ControlTemplate> </Setter.Value>
</Setter.Value> </Setter>
</Setter> </DataTrigger>
</DataTrigger> <DataTrigger Binding="{Binding Text,Converter={StaticResource NotNullOrEmptyToBoolConverter}}" Value="True">
<DataTrigger Binding="{Binding Text,Converter={StaticResource NotNullOrEmptyToBoolConverter}}" Value="True"> <Setter Property="Template">
<Setter Property="Template"> <Setter.Value>
<Setter.Value> <ControlTemplate>
<ControlTemplate> <dd:TextControl x:Name="PART_Text" />
<dd:TextControl x:Name="PART_Text" /> </ControlTemplate>
</ControlTemplate> </Setter.Value>
</Setter.Value> </Setter>
</Setter> </DataTrigger>
</DataTrigger> <DataTrigger Binding="{Binding CustomText}" Value="True">
<DataTrigger Binding="{Binding CustomText}" Value="True"> <Setter Property="Template">
<Setter Property="Template"> <Setter.Value>
<Setter.Value> <ControlTemplate>
<ControlTemplate> <Grid/>
<Grid/> </ControlTemplate>
</ControlTemplate> </Setter.Value>
</Setter.Value> </Setter>
</Setter> </DataTrigger>
</DataTrigger> </Style.Triggers>
</Style.Triggers> </Style>
</Style> </Control.Style>
</Control.Style> </Control>
</Control> </Grid>
</Grid> <dd:BlockItemsContainer x:Name="contain"
<dd:ItemsContainer x:Name="contain"
Margin="20" Margin="20"
ParentPanel="{Binding ElementName=grid}" ParentPanel="{Binding ElementName=grid}"
GetOffSetFunc="{Binding FirstContain.GetOffSetFunc,Mode=OneWayToSource}" GetOffSetFunc="{Binding FirstContain.GetOffSetFunc,Mode=OneWayToSource}"
Border="{Binding FirstContain}"> Border="{Binding FirstContain}">
<ItemsControl x:Name="items" ItemsSource="{Binding FirstContain.Children}"> <dd:BlockItemsControl x:Name="items" ItemsSource="{Binding FirstContain.Children}">
</dd:BlockItemsControl>
</dd:BlockItemsContainer>
</Grid>
</ItemsControl>
</dd:ItemsContainer>
</Grid>
</dd:BlockBorder>
<DataTemplate.Triggers> <DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="true"> <DataTrigger Binding="{Binding IsSelected}" Value="true">
<Setter TargetName="left" Property="Background" Value="#3399FF"/> <Setter TargetName="left" Property="Background" Value="#3399FF"/>

View File

@@ -10,24 +10,24 @@ using AIStudio.Wpf.DiagramDesigner.Models;
namespace AIStudio.Wpf.DiagramDesigner namespace AIStudio.Wpf.DiagramDesigner
{ {
public class ItemsContainerInfo : SelectableViewModelBase public class BlockItemsContainerInfo : SelectableViewModelBase
{ {
public ItemsContainerInfo(BlockDesignerItemViewModel dataItem) : this(null, dataItem) public BlockItemsContainerInfo(BlockDesignerItemViewModel dataItem) : this(null, dataItem)
{ {
} }
public ItemsContainerInfo(IDiagramViewModel root, BlockDesignerItemViewModel dataItem) : base(root) public BlockItemsContainerInfo(IDiagramViewModel root, BlockDesignerItemViewModel dataItem) : base(root)
{ {
this.Parent = dataItem; this.Parent = dataItem;
} }
public ItemsContainerInfo(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer) public BlockItemsContainerInfo(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
{ {
} }
public ItemsContainerInfo(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType) public BlockItemsContainerInfo(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
{ {
} }
@@ -139,7 +139,7 @@ namespace AIStudio.Wpf.DiagramDesigner
get; set; get; set;
} = new ObservableCollection<BlockDesignerItemViewModel>(); } = new ObservableCollection<BlockDesignerItemViewModel>();
public List<ItemsContainerInfo> ChildrenContain public List<BlockItemsContainerInfo> ChildrenContain
{ {
get get
{ {
@@ -227,9 +227,9 @@ namespace AIStudio.Wpf.DiagramDesigner
Children.Remove(child); Children.Remove(child);
} }
public List<ItemsContainerInfo> GetAllContain(ObservableCollection<BlockDesignerItemViewModel> children, bool self) public List<BlockItemsContainerInfo> GetAllContain(ObservableCollection<BlockDesignerItemViewModel> children, bool self)
{ {
List <ItemsContainerInfo> itemsContainers= new List <ItemsContainerInfo>(); List <BlockItemsContainerInfo> itemsContainers= new List <BlockItemsContainerInfo>();
if (self) if (self)
{ {
itemsContainers.Add(this); itemsContainers.Add(this);

View File

@@ -3145,7 +3145,7 @@ namespace AIStudio.Wpf.DiagramDesigner
return new Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo>(parent, next); return new Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo>(parent, next);
} }
public ItemsContainerInfo FindNearContainerToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel) public BlockItemsContainerInfo FindNearContainerToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel)
{ {
if (blockDesignerItemViewModel == null) if (blockDesignerItemViewModel == null)
return null; return null;

View File

@@ -29,7 +29,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
base.InitNew(); base.InitNew();
Contains.Add(new ItemsContainerInfo(this.Root, this)); Contains.Add(new BlockItemsContainerInfo(this.Root, this));
} }
public override void AddChild(BlockDesignerItemViewModel child) public override void AddChild(BlockDesignerItemViewModel child)

View File

@@ -29,7 +29,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
base.InitNew(); base.InitNew();
Contains.Add(new ItemsContainerInfo(this.Root, this)); Contains.Add(new BlockItemsContainerInfo(this.Root, this));
} }
public override void AddChild(BlockDesignerItemViewModel child) public override void AddChild(BlockDesignerItemViewModel child)

View File

@@ -41,7 +41,7 @@ namespace AIStudio.Wpf.DiagramDesigner
get; set; get; set;
} }
public ItemsContainerInfo ParentContain public BlockItemsContainerInfo ParentContain
{ {
get; set; get; set;
} }
@@ -145,12 +145,12 @@ namespace AIStudio.Wpf.DiagramDesigner
})); }));
} }
public ObservableCollection<ItemsContainerInfo> Contains public ObservableCollection<BlockItemsContainerInfo> Contains
{ {
get; set; get; set;
} = new ObservableCollection<ItemsContainerInfo>(); } = new ObservableCollection<BlockItemsContainerInfo>();
public ItemsContainerInfo FirstContain public BlockItemsContainerInfo FirstContain
{ {
get get
{ {
@@ -158,7 +158,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
public List<ItemsContainerInfo> GetAllContain() public List<BlockItemsContainerInfo> GetAllContain()
{ {
return Contains.SelectMany(p => p.GetAllContain(p.Children, true)).ToList(); return Contains.SelectMany(p => p.GetAllContain(p.Children, true)).ToList();
} }

View File

@@ -366,7 +366,7 @@ namespace AIStudio.Wpf.DiagramDesigner
FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType); FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType);
FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection); FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection);
Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo> FindNearPortToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel, bool isExist); Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo> FindNearPortToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel, bool isExist);
ItemsContainerInfo FindNearContainerToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel); BlockItemsContainerInfo FindNearContainerToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel);
void ClearNearPort(); void ClearNearPort();
void ClearNearContain(); void ClearNearContain();
void PreviewNearBlock(List<BlockDesignerItemViewModel> blocks); void PreviewNearBlock(List<BlockDesignerItemViewModel> blocks);