Refactor how data context is handled

This commit is contained in:
Wiesław Šoltés 2024-09-28 23:22:41 +02:00
Родитель d15749f724
Коммит 16bfdd230d
31 изменённых файлов: 268 добавлений и 388 удалений

Просмотреть файл

@ -201,10 +201,12 @@ public partial class MainViewViewModel : ViewModelBase
{ {
var control = new DrawingNode var control = new DrawingNode
{ {
DataContext = Editor.Drawing DrawingSource = Editor.Drawing,
Width = Editor.Drawing.Width,
Height = Editor.Drawing.Height,
}; };
var root = new ExportRoot() var root = new ExportRoot
{ {
Width = Editor.Drawing.Width, Width = Editor.Drawing.Width,
Height = Editor.Drawing.Height, Height = Editor.Drawing.Height,

Просмотреть файл

@ -75,7 +75,6 @@
</UserControl.KeyBindings> </UserControl.KeyBindings>
<DockPanel> <DockPanel>
<views:MenuView ZoomControl="{Binding #EditorControl.ZoomControl}" <views:MenuView ZoomControl="{Binding #EditorControl.ZoomControl}"
DrawingNode="{Binding #EditorControl.DrawingNode}"
x:CompileBindings="False" x:CompileBindings="False"
DockPanel.Dock="Top" /> DockPanel.Dock="Top" />
<Separator IsVisible="False" Classes="horizontal" DockPanel.Dock="Top" /> <Separator IsVisible="False" Classes="horizontal" DockPanel.Dock="Top" />
@ -92,23 +91,12 @@
IsVisible="{Binding IsToolboxVisible}"> IsVisible="{Binding IsToolboxVisible}">
<Separator Classes="vertical" DockPanel.Dock="Right" /> <Separator Classes="vertical" DockPanel.Dock="Right" />
<editor:Toolbox TemplatesSource="{Binding Editor.Templates}" <editor:Toolbox TemplatesSource="{Binding Editor.Templates}"
Drawing="{Binding Editor.Drawing}"
Name="ToolboxView" /> Name="ToolboxView" />
</DockPanel> </DockPanel>
<ThemeVariantScope RequestedThemeVariant="Light" <ThemeVariantScope RequestedThemeVariant="Light"
Grid.Column="1" Grid.ColumnSpan="2"> Grid.Column="1" Grid.ColumnSpan="2">
<editor:Editor Name="EditorControl" <editor:Editor Name="EditorControl"
DataContext="{Binding Editor.Drawing, FallbackValue={x:Null}}" DrawingSource="{Binding Editor.Drawing, FallbackValue={x:Null}}" />
DrawingWidth="{Binding Width}"
DrawingHeight="{Binding Height}"
NodesSource="{Binding Nodes}"
ConnectorsSource="{Binding Connectors}"
EnableSnap="{Binding Settings.EnableSnap}"
SnapX="{Binding Settings.SnapX}"
SnapY="{Binding Settings.SnapY}"
EnableGrid="{Binding Settings.EnableGrid}"
GridCellWidth="{Binding Settings.GridCellWidth}"
GridCellHeight="{Binding Settings.GridCellHeight}"/>
</ThemeVariantScope> </ThemeVariantScope>
<GridSplitter Grid.Column="1" Background="Transparent" /> <GridSplitter Grid.Column="1" Background="Transparent" />
</Grid> </Grid>

Просмотреть файл

@ -9,9 +9,6 @@ public partial class MenuView : UserControl
public static readonly StyledProperty<NodeZoomBorder?> ZoomControlProperty = public static readonly StyledProperty<NodeZoomBorder?> ZoomControlProperty =
AvaloniaProperty.Register<MenuView, NodeZoomBorder?>(nameof(ZoomControl)); AvaloniaProperty.Register<MenuView, NodeZoomBorder?>(nameof(ZoomControl));
public static readonly StyledProperty<DrawingNode?> DrawingNodeProperty =
AvaloniaProperty.Register<MenuView, DrawingNode?>(nameof(DrawingNode));
public MenuView() public MenuView()
{ {
InitializeComponent(); InitializeComponent();
@ -22,10 +19,4 @@ public partial class MenuView : UserControl
get => GetValue(ZoomControlProperty); get => GetValue(ZoomControlProperty);
set => SetValue(ZoomControlProperty, value); set => SetValue(ZoomControlProperty, value);
} }
public DrawingNode? DrawingNode
{
get => GetValue(DrawingNodeProperty);
set => SetValue(DrawingNodeProperty, value);
}
} }

Просмотреть файл

@ -10,6 +10,15 @@ namespace NodeEditor.Behaviors;
public class ConnectorsSelectedBehavior : Behavior<ItemsControl> public class ConnectorsSelectedBehavior : Behavior<ItemsControl>
{ {
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<ConnectorsSelectedBehavior, IDrawingNode?>(nameof(DrawingSource));
public IDrawingNode? DrawingSource
{
get => GetValue(DrawingSourceProperty);
set => SetValue(DrawingSourceProperty, value);
}
private IDisposable? _dataContextDisposable; private IDisposable? _dataContextDisposable;
private IDrawingNode? _drawingNode; private IDrawingNode? _drawingNode;
@ -66,7 +75,7 @@ public class ConnectorsSelectedBehavior : Behavior<ItemsControl>
private void DrawingNode_SelectionChanged(object? sender, EventArgs e) private void DrawingNode_SelectionChanged(object? sender, EventArgs e)
{ {
if (AssociatedObject?.DataContext is not IDrawingNode) if (DrawingSource is not IDrawingNode)
{ {
return; return;
} }

Просмотреть файл

@ -9,9 +9,18 @@ namespace NodeEditor.Behaviors;
public class DrawingDropHandler : DefaultDropHandler public class DrawingDropHandler : DefaultDropHandler
{ {
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<DrawingDropHandler, IDrawingNode?>(nameof(DrawingSource));
public static readonly StyledProperty<Control?> RelativeToProperty = public static readonly StyledProperty<Control?> RelativeToProperty =
AvaloniaProperty.Register<DrawingDropHandler, Control?>(nameof(RelativeTo)); AvaloniaProperty.Register<DrawingDropHandler, Control?>(nameof(RelativeTo));
public IDrawingNode? DrawingSource
{
get => GetValue(DrawingSourceProperty);
set => SetValue(DrawingSourceProperty, value);
}
public Control? RelativeTo public Control? RelativeTo
{ {
get => GetValue(RelativeToProperty); get => GetValue(RelativeToProperty);
@ -27,9 +36,9 @@ public class DrawingDropHandler : DefaultDropHandler
} }
var point = GetPosition(relativeTo, e); var point = GetPosition(relativeTo, e);
if (relativeTo is DrawingNode drawingNode) if (relativeTo is DrawingNode { DrawingSource: not null } drawingNode)
{ {
point = SnapHelper.Snap(point, drawingNode.SnapX, drawingNode.SnapY, drawingNode.EnableSnap); point = SnapHelper.Snap(point, drawingNode.DrawingSource.Settings.SnapX, drawingNode.DrawingSource.Settings.SnapY, drawingNode.DrawingSource.Settings.EnableSnap);
} }
if (e.Data.Contains(DataFormats.Text)) if (e.Data.Contains(DataFormats.Text))

Просмотреть файл

@ -1,4 +1,5 @@
using Avalonia.Controls; using Avalonia;
using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Xaml.Interactivity; using Avalonia.Xaml.Interactivity;
@ -8,6 +9,15 @@ namespace NodeEditor.Behaviors;
public class DrawingMovedBehavior : Behavior<ItemsControl> public class DrawingMovedBehavior : Behavior<ItemsControl>
{ {
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<DrawingMovedBehavior, IDrawingNode?>(nameof(DrawingSource));
public IDrawingNode? DrawingSource
{
get => GetValue(DrawingSourceProperty);
set => SetValue(DrawingSourceProperty, value);
}
protected override void OnAttached() protected override void OnAttached()
{ {
base.OnAttached(); base.OnAttached();
@ -30,7 +40,7 @@ public class DrawingMovedBehavior : Behavior<ItemsControl>
private void Moved(object? sender, PointerEventArgs e) private void Moved(object? sender, PointerEventArgs e)
{ {
if (AssociatedObject?.DataContext is not IDrawingNode drawingNode) if (DrawingSource is not IDrawingNode drawingNode)
{ {
return; return;
} }

Просмотреть файл

@ -1,4 +1,5 @@
using Avalonia.Controls; using Avalonia;
using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Xaml.Interactivity; using Avalonia.Xaml.Interactivity;
@ -8,6 +9,15 @@ namespace NodeEditor.Behaviors;
public class DrawingPressedBehavior : Behavior<ItemsControl> public class DrawingPressedBehavior : Behavior<ItemsControl>
{ {
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<DrawingPressedBehavior, IDrawingNode?>(nameof(DrawingSource));
public IDrawingNode? DrawingSource
{
get => GetValue(DrawingSourceProperty);
set => SetValue(DrawingSourceProperty, value);
}
protected override void OnAttached() protected override void OnAttached()
{ {
base.OnAttached(); base.OnAttached();
@ -35,7 +45,7 @@ public class DrawingPressedBehavior : Behavior<ItemsControl>
return; return;
} }
if (AssociatedObject?.DataContext is not IDrawingNode drawingNode) if (DrawingSource is not IDrawingNode drawingNode)
{ {
return; return;
} }

Просмотреть файл

@ -12,21 +12,15 @@ namespace NodeEditor.Behaviors;
public class DrawingSelectionBehavior : Behavior<ItemsControl> public class DrawingSelectionBehavior : Behavior<ItemsControl>
{ {
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<DrawingSelectionBehavior, IDrawingNode?>(nameof(DrawingSource));
public static readonly StyledProperty<Control?> InputSourceProperty = public static readonly StyledProperty<Control?> InputSourceProperty =
AvaloniaProperty.Register<DrawingSelectionBehavior, Control?>(nameof(InputSource)); AvaloniaProperty.Register<DrawingSelectionBehavior, Control?>(nameof(InputSource));
public static readonly StyledProperty<Canvas?> AdornerCanvasProperty = public static readonly StyledProperty<Canvas?> AdornerCanvasProperty =
AvaloniaProperty.Register<DrawingSelectionBehavior, Canvas?>(nameof(AdornerCanvas)); AvaloniaProperty.Register<DrawingSelectionBehavior, Canvas?>(nameof(AdornerCanvas));
public static readonly StyledProperty<bool> EnableSnapProperty =
AvaloniaProperty.Register<DrawingSelectionBehavior, bool>(nameof(EnableSnap));
public static readonly StyledProperty<double> SnapXProperty =
AvaloniaProperty.Register<DrawingSelectionBehavior, double>(nameof(SnapX), 1.0);
public static readonly StyledProperty<double> SnapYProperty =
AvaloniaProperty.Register<DrawingSelectionBehavior, double>(nameof(SnapY), 1.0);
private IDisposable? _dataContextDisposable; private IDisposable? _dataContextDisposable;
private IDrawingNode? _drawingNode; private IDrawingNode? _drawingNode;
private SelectionAdorner? _selectionAdorner; private SelectionAdorner? _selectionAdorner;
@ -36,6 +30,12 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
private Rect _selectedRect; private Rect _selectedRect;
private Control? _inputSource; private Control? _inputSource;
public IDrawingNode? DrawingSource
{
get => GetValue(DrawingSourceProperty);
set => SetValue(DrawingSourceProperty, value);
}
public Control? InputSource public Control? InputSource
{ {
get => GetValue(InputSourceProperty); get => GetValue(InputSourceProperty);
@ -48,24 +48,6 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
set => SetValue(AdornerCanvasProperty, value); set => SetValue(AdornerCanvasProperty, value);
} }
public bool EnableSnap
{
get => GetValue(EnableSnapProperty);
set => SetValue(EnableSnapProperty, value);
}
public double SnapX
{
get => GetValue(SnapXProperty);
set => SetValue(SnapXProperty, value);
}
public double SnapY
{
get => GetValue(SnapYProperty);
set => SetValue(SnapYProperty, value);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{ {
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
@ -95,12 +77,12 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
_inputSource.AddHandler(InputElement.PointerCaptureLostEvent, CaptureLost, RoutingStrategies.Tunnel | RoutingStrategies.Bubble); _inputSource.AddHandler(InputElement.PointerCaptureLostEvent, CaptureLost, RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
_inputSource.AddHandler(InputElement.PointerMovedEvent, Moved, RoutingStrategies.Tunnel | RoutingStrategies.Bubble); _inputSource.AddHandler(InputElement.PointerMovedEvent, Moved, RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
_dataContextDisposable = AssociatedObject _dataContextDisposable = this
.GetObservable(StyledElement.DataContextProperty) .GetObservable(DrawingSourceProperty)
.Subscribe(new AnonymousObserver<object?>( .Subscribe(new AnonymousObserver<IDrawingNode?>(
x => x =>
{ {
if (x is IDrawingNode drawingNode) if (x is { } drawingNode)
{ {
if (_drawingNode == drawingNode) if (_drawingNode == drawingNode)
{ {
@ -163,7 +145,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
private void DrawingNode_SelectionChanged(object? sender, EventArgs e) private void DrawingNode_SelectionChanged(object? sender, EventArgs e)
{ {
if (AssociatedObject?.DataContext is not IDrawingNode) if (DrawingSource is null)
{ {
return; return;
} }
@ -175,7 +157,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 }) if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 })
{ {
_selectedRect = HitTestHelper.CalculateSelectedRect(AssociatedObject); _selectedRect = HitTestHelper.CalculateSelectedRect(_drawingNode, AssociatedObject);
if (_selectedAdorner is not null) if (_selectedAdorner is not null)
{ {
@ -203,7 +185,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
var info = e.GetCurrentPoint(_inputSource); var info = e.GetCurrentPoint(_inputSource);
if (AssociatedObject?.DataContext is not IDrawingNode drawingNode) if (DrawingSource is not { } drawingNode)
{ {
return; return;
} }
@ -236,11 +218,11 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
if (_selectedRect.Contains(position)) if (_selectedRect.Contains(position))
{ {
_dragSelectedItems = true; _dragSelectedItems = true;
_start = SnapHelper.Snap(position, SnapX, SnapY, EnableSnap); _start = SnapHelper.Snap(position, drawingNode.Settings.SnapX, drawingNode.Settings.SnapY, drawingNode.Settings.EnableSnap);
} }
else else
{ {
HitTestHelper.FindSelectedNodes(AssociatedObject, pointerHitTestRect); HitTestHelper.FindSelectedNodes(drawingNode, AssociatedObject, pointerHitTestRect);
selectedNodes = drawingNode.GetSelectedNodes(); selectedNodes = drawingNode.GetSelectedNodes();
selectedConnectors = drawingNode.GetSelectedConnectors(); selectedConnectors = drawingNode.GetSelectedConnectors();
@ -248,7 +230,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 }) if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 })
{ {
_dragSelectedItems = true; _dragSelectedItems = true;
_start = SnapHelper.Snap(position, SnapX, SnapY, EnableSnap); _start = SnapHelper.Snap(position, drawingNode.Settings.SnapX, drawingNode.Settings.SnapY, drawingNode.Settings.EnableSnap);
} }
else else
{ {
@ -264,7 +246,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
} }
else else
{ {
HitTestHelper.FindSelectedNodes(AssociatedObject, pointerHitTestRect); HitTestHelper.FindSelectedNodes(drawingNode, AssociatedObject, pointerHitTestRect);
selectedNodes = drawingNode.GetSelectedNodes(); selectedNodes = drawingNode.GetSelectedNodes();
selectedConnectors = drawingNode.GetSelectedConnectors(); selectedConnectors = drawingNode.GetSelectedConnectors();
@ -272,7 +254,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 }) if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 })
{ {
_dragSelectedItems = true; _dragSelectedItems = true;
_start = SnapHelper.Snap(position, SnapX, SnapY, EnableSnap); _start = SnapHelper.Snap(position, drawingNode.Settings.SnapX, drawingNode.Settings.SnapY, drawingNode.Settings.EnableSnap);
} }
} }
@ -284,7 +266,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
RemoveSelected(); RemoveSelected();
if (e.Source is not Control { DataContext: not IDrawingNode }) // TODO: if (e.Source is not Control { DataContext: not IDrawingNode })
{ {
AddSelection(position.X, position.Y); AddSelection(position.X, position.Y);
} }
@ -298,15 +280,15 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
{ {
if (Equals(e.Pointer.Captured, _inputSource)) if (Equals(e.Pointer.Captured, _inputSource))
{ {
if (e.InitialPressMouseButton == MouseButton.Left && AssociatedObject?.DataContext is IDrawingNode) if (e.InitialPressMouseButton == MouseButton.Left && DrawingSource is IDrawingNode drawingNode)
{ {
_dragSelectedItems = false; _dragSelectedItems = false;
if (e.Source is not Control { DataContext: not IDrawingNode }) // TODO: if (e.Source is not Control { DataContext: not IDrawingNode })
{ {
if (_selectionAdorner is not null) if (_selectionAdorner is not null)
{ {
HitTestHelper.FindSelectedNodes(AssociatedObject, _selectionAdorner.GetRect()); HitTestHelper.FindSelectedNodes(drawingNode, AssociatedObject, _selectionAdorner.GetRect());
} }
RemoveSelection(); RemoveSelection();
@ -326,19 +308,19 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
{ {
var info = e.GetCurrentPoint(_inputSource); var info = e.GetCurrentPoint(_inputSource);
if (Equals(e.Pointer.Captured, _inputSource) && info.Properties.IsLeftButtonPressed && AssociatedObject?.DataContext is IDrawingNode) if (Equals(e.Pointer.Captured, _inputSource) && info.Properties.IsLeftButtonPressed && DrawingSource is IDrawingNode)
{ {
var position = e.GetPosition(AssociatedObject); var position = e.GetPosition(AssociatedObject);
if (_dragSelectedItems) if (_dragSelectedItems)
{ {
if (AssociatedObject?.DataContext is IDrawingNode drawingNode) if (DrawingSource is IDrawingNode drawingNode)
{ {
var selectedNodes = drawingNode.GetSelectedNodes(); var selectedNodes = drawingNode.GetSelectedNodes();
if (selectedNodes is { Count: > 0 } && drawingNode.Nodes is { Count: > 0 }) if (selectedNodes is { Count: > 0 } && drawingNode.Nodes is { Count: > 0 })
{ {
position = SnapHelper.Snap(position, SnapX, SnapY, EnableSnap); position = SnapHelper.Snap(position, drawingNode.Settings.SnapX, drawingNode.Settings.SnapY, drawingNode.Settings.EnableSnap);
var deltaX = position.X - _start.X; var deltaX = position.X - _start.X;
var deltaY = position.Y - _start.Y; var deltaY = position.Y - _start.Y;
@ -353,7 +335,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
} }
} }
var selectedRect = HitTestHelper.CalculateSelectedRect(AssociatedObject); var selectedRect = HitTestHelper.CalculateSelectedRect(drawingNode, AssociatedObject);
_selectedRect = selectedRect; _selectedRect = selectedRect;
@ -365,7 +347,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
} }
else else
{ {
if (e.Source is not Control { DataContext: not IDrawingNode }) // TODO: if (e.Source is not Control { DataContext: not IDrawingNode })
{ {
UpdateSelection(position.X, position.Y); UpdateSelection(position.X, position.Y);

Просмотреть файл

@ -8,13 +8,13 @@ namespace NodeEditor.Behaviors;
public class InsertTemplateOnDoubleTappedBehavior : Behavior<ListBoxItem> public class InsertTemplateOnDoubleTappedBehavior : Behavior<ListBoxItem>
{ {
public static readonly StyledProperty<IDrawingNode?> DrawingProperty = public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<InsertTemplateOnDoubleTappedBehavior, IDrawingNode?>(nameof(Drawing)); AvaloniaProperty.Register<InsertTemplateOnDoubleTappedBehavior, IDrawingNode?>(nameof(DrawingSource));
public IDrawingNode? Drawing public IDrawingNode? DrawingSource
{ {
get => GetValue(DrawingProperty); get => GetValue(DrawingSourceProperty);
set => SetValue(DrawingProperty, value); set => SetValue(DrawingSourceProperty, value);
} }
protected override void OnAttached() protected override void OnAttached()
@ -37,7 +37,7 @@ public class InsertTemplateOnDoubleTappedBehavior : Behavior<ListBoxItem>
private void DoubleTapped(object? sender, RoutedEventArgs args) private void DoubleTapped(object? sender, RoutedEventArgs args)
{ {
if (AssociatedObject is { DataContext: INodeTemplate template } && Drawing is { } drawing) if (AssociatedObject is { DataContext: INodeTemplate template } && DrawingSource is { } drawing)
{ {
var node = drawing.Clone(template.Template); var node = drawing.Clone(template.Template);
if (node is not null) if (node is not null)

Просмотреть файл

@ -11,6 +11,15 @@ namespace NodeEditor.Behaviors;
public class NodesSelectedBehavior : Behavior<ItemsControl> public class NodesSelectedBehavior : Behavior<ItemsControl>
{ {
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<NodesSelectedBehavior, IDrawingNode?>(nameof(DrawingSource));
public IDrawingNode? DrawingSource
{
get => GetValue(DrawingSourceProperty);
set => SetValue(DrawingSourceProperty, value);
}
private IDisposable? _dataContextDisposable; private IDisposable? _dataContextDisposable;
private IDrawingNode? _drawingNode; private IDrawingNode? _drawingNode;
@ -66,7 +75,7 @@ public class NodesSelectedBehavior : Behavior<ItemsControl>
private void DrawingNode_SelectionChanged(object? sender, EventArgs e) private void DrawingNode_SelectionChanged(object? sender, EventArgs e)
{ {
if (AssociatedObject?.DataContext is not IDrawingNode) if (DrawingSource is not IDrawingNode)
{ {
return; return;
} }

Просмотреть файл

@ -1,14 +1,23 @@
using Avalonia.Controls.Presenters; using Avalonia;
using Avalonia.Controls.Presenters;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Xaml.Interactivity; using Avalonia.Xaml.Interactivity;
using NodeEditor.Controls;
using NodeEditor.Model; using NodeEditor.Model;
namespace NodeEditor.Behaviors; namespace NodeEditor.Behaviors;
public class PinPressedBehavior : Behavior<ContentPresenter> public class PinPressedBehavior : Behavior<ContentPresenter>
{ {
public static readonly StyledProperty<IPin?> PinSourceProperty =
AvaloniaProperty.Register<PinPressedBehavior, IPin?>(nameof(PinSource));
public IPin? PinSource
{
get => GetValue(PinSourceProperty);
set => SetValue(PinSourceProperty, value);
}
protected override void OnAttached() protected override void OnAttached()
{ {
base.OnAttached(); base.OnAttached();

Просмотреть файл

@ -9,6 +9,9 @@ namespace NodeEditor.Controls;
[PseudoClasses(":selected")] [PseudoClasses(":selected")]
public class Connector : Shape public class Connector : Shape
{ {
public static readonly StyledProperty<IConnector?> ConnectorSourceProperty =
AvaloniaProperty.Register<Connector, IConnector?>(nameof(ConnectorSource));
public static readonly StyledProperty<Point> StartPointProperty = public static readonly StyledProperty<Point> StartPointProperty =
AvaloniaProperty.Register<Connector, Point>(nameof(StartPoint)); AvaloniaProperty.Register<Connector, Point>(nameof(StartPoint));
@ -31,6 +34,12 @@ public class Connector : Shape
OrientationProperty); OrientationProperty);
} }
public IConnector? ConnectorSource
{
get => GetValue(ConnectorSourceProperty);
set => SetValue(ConnectorSourceProperty, value);
}
public Point StartPoint public Point StartPoint
{ {
get => GetValue(StartPointProperty); get => GetValue(StartPointProperty);

Просмотреть файл

@ -1,17 +1,18 @@
using System.Collections; using System.Collections;
using Avalonia; using Avalonia;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using NodeEditor.Model;
namespace NodeEditor.Controls; namespace NodeEditor.Controls;
public class Connectors : TemplatedControl public class Connectors : TemplatedControl
{ {
public static readonly StyledProperty<IEnumerable?> ConnectorsSourceProperty = public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<Connectors, IEnumerable?>(nameof(ConnectorsSource)); AvaloniaProperty.Register<Connectors, IDrawingNode?>(nameof(DrawingSource));
public IEnumerable? ConnectorsSource public IDrawingNode? DrawingSource
{ {
get => GetValue(ConnectorsSourceProperty); get => GetValue(DrawingSourceProperty);
set => SetValue(ConnectorsSourceProperty, value); set => SetValue(DrawingSourceProperty, value);
} }
} }

Просмотреть файл

@ -1,17 +1,14 @@
using System.Collections; using Avalonia;
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using NodeEditor.Model;
namespace NodeEditor.Controls; namespace NodeEditor.Controls;
public class DrawingNode : TemplatedControl public class DrawingNode : TemplatedControl
{ {
public static readonly StyledProperty<IEnumerable?> NodesSourceProperty = public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<DrawingNode, IEnumerable?>(nameof(NodesSource)); AvaloniaProperty.Register<DrawingNode, IDrawingNode?>(nameof(DrawingSource));
public static readonly StyledProperty<IEnumerable?> ConnectorsSourceProperty =
AvaloniaProperty.Register<DrawingNode, IEnumerable?>(nameof(ConnectorsSource));
public static readonly StyledProperty<Control?> InputSourceProperty = public static readonly StyledProperty<Control?> InputSourceProperty =
AvaloniaProperty.Register<DrawingNode, Control?>(nameof(InputSource)); AvaloniaProperty.Register<DrawingNode, Control?>(nameof(InputSource));
@ -19,34 +16,10 @@ public class DrawingNode : TemplatedControl
public static readonly StyledProperty<Canvas?> AdornerCanvasProperty = public static readonly StyledProperty<Canvas?> AdornerCanvasProperty =
AvaloniaProperty.Register<DrawingNode, Canvas?>(nameof(AdornerCanvas)); AvaloniaProperty.Register<DrawingNode, Canvas?>(nameof(AdornerCanvas));
public static readonly StyledProperty<bool> EnableSnapProperty = public IDrawingNode? DrawingSource
AvaloniaProperty.Register<DrawingNode, bool>(nameof(EnableSnap));
public static readonly StyledProperty<double> SnapXProperty =
AvaloniaProperty.Register<DrawingNode, double>(nameof(SnapX), 1.0);
public static readonly StyledProperty<double> SnapYProperty =
AvaloniaProperty.Register<DrawingNode, double>(nameof(SnapY), 1.0);
public static readonly StyledProperty<bool> EnableGridProperty =
AvaloniaProperty.Register<DrawingNode, bool>(nameof(EnableGrid));
public static readonly StyledProperty<double> GridCellWidthProperty =
AvaloniaProperty.Register<DrawingNode, double>(nameof(GridCellWidth));
public static readonly StyledProperty<double> GridCellHeightProperty =
AvaloniaProperty.Register<DrawingNode, double>(nameof(GridCellHeight));
public IEnumerable? NodesSource
{ {
get => GetValue(NodesSourceProperty); get => GetValue(DrawingSourceProperty);
set => SetValue(NodesSourceProperty, value); set => SetValue(DrawingSourceProperty, value);
}
public IEnumerable? ConnectorsSource
{
get => GetValue(ConnectorsSourceProperty);
set => SetValue(ConnectorsSourceProperty, value);
} }
public Control? InputSource public Control? InputSource
@ -60,40 +33,4 @@ public class DrawingNode : TemplatedControl
get => GetValue(AdornerCanvasProperty); get => GetValue(AdornerCanvasProperty);
set => SetValue(AdornerCanvasProperty, value); set => SetValue(AdornerCanvasProperty, value);
} }
public bool EnableSnap
{
get => GetValue(EnableSnapProperty);
set => SetValue(EnableSnapProperty, value);
}
public double SnapX
{
get => GetValue(SnapXProperty);
set => SetValue(SnapXProperty, value);
}
public double SnapY
{
get => GetValue(SnapYProperty);
set => SetValue(SnapYProperty, value);
}
public bool EnableGrid
{
get => GetValue(EnableGridProperty);
set => SetValue(EnableGridProperty, value);
}
public double GridCellWidth
{
get => GetValue(GridCellWidthProperty);
set => SetValue(GridCellWidthProperty, value);
}
public double GridCellHeight
{
get => GetValue(GridCellHeightProperty);
set => SetValue(GridCellHeightProperty, value);
}
} }

Просмотреть файл

@ -4,19 +4,16 @@ using Avalonia.Controls;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Data; using Avalonia.Data;
using NodeEditor.Model;
namespace NodeEditor.Controls; namespace NodeEditor.Controls;
[TemplatePart("PART_ZoomBorder", typeof(NodeZoomBorder))] [TemplatePart("PART_ZoomBorder", typeof(NodeZoomBorder))]
[TemplatePart("PART_Drawing", typeof(DrawingNode))]
[TemplatePart("PART_AdornerCanvas", typeof(Canvas))] [TemplatePart("PART_AdornerCanvas", typeof(Canvas))]
public class Editor : TemplatedControl public class Editor : TemplatedControl
{ {
public static readonly StyledProperty<IEnumerable?> NodesSourceProperty = public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<Editor, IEnumerable?>(nameof(NodesSource)); AvaloniaProperty.Register<Editor, IDrawingNode?>(nameof(DrawingSource));
public static readonly StyledProperty<IEnumerable?> ConnectorsSourceProperty =
AvaloniaProperty.Register<Editor, IEnumerable?>(nameof(ConnectorsSource));
public static readonly StyledProperty<Control?> InputSourceProperty = public static readonly StyledProperty<Control?> InputSourceProperty =
AvaloniaProperty.Register<Editor, Control?>(nameof(InputSource)); AvaloniaProperty.Register<Editor, Control?>(nameof(InputSource));
@ -24,46 +21,13 @@ public class Editor : TemplatedControl
public static readonly StyledProperty<Canvas?> AdornerCanvasProperty = public static readonly StyledProperty<Canvas?> AdornerCanvasProperty =
AvaloniaProperty.Register<Editor, Canvas?>(nameof(AdornerCanvas)); AvaloniaProperty.Register<Editor, Canvas?>(nameof(AdornerCanvas));
public static readonly StyledProperty<bool> EnableSnapProperty =
AvaloniaProperty.Register<Editor, bool>(nameof(EnableSnap), false, false, BindingMode.TwoWay);
public static readonly StyledProperty<double> SnapXProperty =
AvaloniaProperty.Register<Editor, double>(nameof(SnapX), 1.0, false, BindingMode.TwoWay);
public static readonly StyledProperty<double> SnapYProperty =
AvaloniaProperty.Register<Editor, double>(nameof(SnapY), 1.0, false, BindingMode.TwoWay);
public static readonly StyledProperty<bool> EnableGridProperty =
AvaloniaProperty.Register<Editor, bool>(nameof(EnableGrid), false, false, BindingMode.TwoWay);
public static readonly StyledProperty<double> GridCellWidthProperty =
AvaloniaProperty.Register<Editor, double>(nameof(GridCellWidth), 15.0, false, BindingMode.TwoWay);
public static readonly StyledProperty<double> GridCellHeightProperty =
AvaloniaProperty.Register<Editor, double>(nameof(GridCellHeight), 15.0, false, BindingMode.TwoWay);
public static readonly StyledProperty<double> DrawingWidthProperty =
AvaloniaProperty.Register<Editor, double>(nameof(DrawingWidth), 0.0, false, BindingMode.TwoWay);
public static readonly StyledProperty<double> DrawingHeightProperty =
AvaloniaProperty.Register<Editor, double>(nameof(DrawingHeight), 0.0, false, BindingMode.TwoWay);
public static readonly StyledProperty<NodeZoomBorder?> ZoomControlProperty = public static readonly StyledProperty<NodeZoomBorder?> ZoomControlProperty =
AvaloniaProperty.Register<Editor, NodeZoomBorder?>(nameof(ZoomControl)); AvaloniaProperty.Register<Editor, NodeZoomBorder?>(nameof(ZoomControl));
public static readonly StyledProperty<DrawingNode?> DrawingNodeProperty = public IDrawingNode? DrawingSource
AvaloniaProperty.Register<Editor, DrawingNode?>(nameof(DrawingNode));
public IEnumerable? NodesSource
{ {
get => GetValue(NodesSourceProperty); get => GetValue(DrawingSourceProperty);
set => SetValue(NodesSourceProperty, value); set => SetValue(DrawingSourceProperty, value);
}
public IEnumerable? ConnectorsSource
{
get => GetValue(ConnectorsSourceProperty);
set => SetValue(ConnectorsSourceProperty, value);
} }
public Control? InputSource public Control? InputSource
@ -78,72 +42,17 @@ public class Editor : TemplatedControl
set => SetValue(AdornerCanvasProperty, value); set => SetValue(AdornerCanvasProperty, value);
} }
public bool EnableSnap
{
get => GetValue(EnableSnapProperty);
set => SetValue(EnableSnapProperty, value);
}
public double SnapX
{
get => GetValue(SnapXProperty);
set => SetValue(SnapXProperty, value);
}
public double SnapY
{
get => GetValue(SnapYProperty);
set => SetValue(SnapYProperty, value);
}
public bool EnableGrid
{
get => GetValue(EnableGridProperty);
set => SetValue(EnableGridProperty, value);
}
public double GridCellWidth
{
get => GetValue(GridCellWidthProperty);
set => SetValue(GridCellWidthProperty, value);
}
public double GridCellHeight
{
get => GetValue(GridCellHeightProperty);
set => SetValue(GridCellHeightProperty, value);
}
public double DrawingWidth
{
get => GetValue(DrawingWidthProperty);
set => SetValue(DrawingWidthProperty, value);
}
public double DrawingHeight
{
get => GetValue(DrawingHeightProperty);
set => SetValue(DrawingHeightProperty, value);
}
public NodeZoomBorder? ZoomControl public NodeZoomBorder? ZoomControl
{ {
get => GetValue(ZoomControlProperty); get => GetValue(ZoomControlProperty);
set => SetValue(ZoomControlProperty, value); set => SetValue(ZoomControlProperty, value);
} }
public DrawingNode? DrawingNode
{
get => GetValue(DrawingNodeProperty);
set => SetValue(DrawingNodeProperty, value);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);
ZoomControl = e.NameScope.Find<NodeZoomBorder>("PART_ZoomBorder"); ZoomControl = e.NameScope.Find<NodeZoomBorder>("PART_ZoomBorder");
DrawingNode = e.NameScope.Find<DrawingNode>("PART_DrawingNode");
AdornerCanvas = e.NameScope.Find<Canvas>("PART_AdornerCanvas"); AdornerCanvas = e.NameScope.Find<Canvas>("PART_AdornerCanvas");
} }
} }

Просмотреть файл

@ -2,18 +2,19 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
using NodeEditor.Model;
namespace NodeEditor.Controls; namespace NodeEditor.Controls;
[PseudoClasses(":selected")] [PseudoClasses(":selected")]
public class Node : ContentControl public class Node : ContentControl
{ {
public static readonly StyledProperty<IEnumerable?> PinsSourceProperty = public static readonly StyledProperty<INode?> NodeSourceProperty =
AvaloniaProperty.Register<Node, IEnumerable?>(nameof(PinsSource)); AvaloniaProperty.Register<Node, INode?>(nameof(NodeSource));
public IEnumerable? PinsSource public INode? NodeSource
{ {
get => GetValue(PinsSourceProperty); get => GetValue(NodeSourceProperty);
set => SetValue(PinsSourceProperty, value); set => SetValue(NodeSourceProperty, value);
} }
} }

Просмотреть файл

@ -1,17 +1,37 @@
using System.Collections; using System.Collections;
using Avalonia; using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using NodeEditor.Model;
namespace NodeEditor.Controls; namespace NodeEditor.Controls;
public class Nodes : TemplatedControl public class Nodes : TemplatedControl
{ {
public static readonly StyledProperty<IEnumerable?> NodesSourceProperty = public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
AvaloniaProperty.Register<Nodes, IEnumerable?>(nameof(NodesSource)); AvaloniaProperty.Register<Nodes, IDrawingNode?>(nameof(DrawingSource));
public IEnumerable? NodesSource public static readonly StyledProperty<Control?> InputSourceProperty =
AvaloniaProperty.Register<Nodes, Control?>(nameof(InputSource));
public static readonly StyledProperty<Canvas?> AdornerCanvasProperty =
AvaloniaProperty.Register<Nodes, Canvas?>(nameof(AdornerCanvas));
public IDrawingNode? DrawingSource
{ {
get => GetValue(NodesSourceProperty); get => GetValue(DrawingSourceProperty);
set => SetValue(NodesSourceProperty, value); set => SetValue(DrawingSourceProperty, value);
}
public Control? InputSource
{
get => GetValue(InputSourceProperty);
set => SetValue(InputSourceProperty, value);
}
public Canvas? AdornerCanvas
{
get => GetValue(AdornerCanvasProperty);
set => SetValue(AdornerCanvasProperty, value);
} }
} }

Просмотреть файл

@ -6,12 +6,21 @@ namespace NodeEditor.Controls;
public class Pin : TemplatedControl public class Pin : TemplatedControl
{ {
public static readonly StyledProperty<IPin?> PinSourceProperty =
AvaloniaProperty.Register<Pin, IPin?>(nameof(PinSource));
public static readonly StyledProperty<PinAlignment> AlignmentProperty = public static readonly StyledProperty<PinAlignment> AlignmentProperty =
AvaloniaProperty.Register<Pin, PinAlignment>(nameof(Alignment)); AvaloniaProperty.Register<Pin, PinAlignment>(nameof(Alignment));
public static readonly StyledProperty<string?> IdProperty = public static readonly StyledProperty<string?> IdProperty =
AvaloniaProperty.Register<Pin, string?>(nameof(Id)); AvaloniaProperty.Register<Pin, string?>(nameof(Id));
public IPin? PinSource
{
get => GetValue(PinSourceProperty);
set => SetValue(PinSourceProperty, value);
}
public PinAlignment Alignment public PinAlignment Alignment
{ {
get => GetValue(AlignmentProperty); get => GetValue(AlignmentProperty);

Просмотреть файл

@ -1,17 +1,18 @@
using System.Collections; using System.Collections;
using Avalonia; using Avalonia;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using NodeEditor.Model;
namespace NodeEditor.Controls; namespace NodeEditor.Controls;
public class Pins : TemplatedControl public class Pins : TemplatedControl
{ {
public static readonly StyledProperty<IEnumerable?> PinsSourceProperty = public static readonly StyledProperty<INode?> NodeSourceProperty =
AvaloniaProperty.Register<Pins, IEnumerable?>(nameof(PinsSource)); AvaloniaProperty.Register<Pins, INode?>(nameof(NodeSource));
public IEnumerable? PinsSource public INode? NodeSource
{ {
get => GetValue(PinsSourceProperty); get => GetValue(NodeSourceProperty);
set => SetValue(PinsSourceProperty, value); set => SetValue(NodeSourceProperty, value);
} }
} }

Просмотреть файл

@ -1,4 +1,5 @@
using System.Collections; using System.Collections;
using System.Collections.Generic;
using Avalonia; using Avalonia;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using NodeEditor.Model; using NodeEditor.Model;
@ -7,21 +8,12 @@ namespace NodeEditor.Controls;
public class Toolbox : TemplatedControl public class Toolbox : TemplatedControl
{ {
public static readonly StyledProperty<IEnumerable?> TemplatesSourceProperty = public static readonly StyledProperty<IEnumerable<INodeTemplate>?> TemplatesSourceProperty =
AvaloniaProperty.Register<Toolbox, IEnumerable?>(nameof(TemplatesSource)); AvaloniaProperty.Register<Toolbox, IEnumerable<INodeTemplate>?>(nameof(TemplatesSource));
public static readonly StyledProperty<IDrawingNode?> DrawingProperty = public IEnumerable<INodeTemplate>? TemplatesSource
AvaloniaProperty.Register<Toolbox, IDrawingNode?>(nameof(Drawing));
public IEnumerable? TemplatesSource
{ {
get => GetValue(TemplatesSourceProperty); get => GetValue(TemplatesSourceProperty);
set => SetValue(TemplatesSourceProperty, value); set => SetValue(TemplatesSourceProperty, value);
} }
public IDrawingNode? Drawing
{
get => GetValue(DrawingProperty);
set => SetValue(DrawingProperty, value);
}
} }

Просмотреть файл

@ -167,13 +167,8 @@ internal static class HitTestHelper
new Point(bottomRightX, bottomRightY)); new Point(bottomRightX, bottomRightY));
} }
public static void FindSelectedNodes(ItemsControl? itemsControl, Rect rect) public static void FindSelectedNodes(IDrawingNode drawingNode, ItemsControl? itemsControl, Rect rect)
{ {
if (itemsControl?.DataContext is not IDrawingNode drawingNode)
{
return;
}
drawingNode.NotifyDeselectedNodes(); drawingNode.NotifyDeselectedNodes();
drawingNode.NotifyDeselectedConnectors(); drawingNode.NotifyDeselectedConnectors();
drawingNode.SetSelectedNodes(null); drawingNode.SetSelectedNodes(null);
@ -245,13 +240,8 @@ internal static class HitTestHelper
} }
} }
public static Rect CalculateSelectedRect(ItemsControl? itemsControl) public static Rect CalculateSelectedRect(IDrawingNode drawingNode, ItemsControl? itemsControl)
{ {
if (itemsControl?.DataContext is not IDrawingNode drawingNode)
{
return default;
}
var selectedRect = new Rect(); var selectedRect = new Rect();
itemsControl.UpdateLayout(); itemsControl.UpdateLayout();

Просмотреть файл

@ -11,7 +11,7 @@
<Setter Property="StrokeThickness" Value="2" /> <Setter Property="StrokeThickness" Value="2" />
<Setter Property="ClipToBounds" Value="False" /> <Setter Property="ClipToBounds" Value="False" />
<Setter Property="ContextFlyout"> <Setter Property="ContextFlyout" x:DataType="controls:Connector">
<Setter.Value> <Setter.Value>
<Flyout> <Flyout>
<DockPanel> <DockPanel>
@ -19,19 +19,19 @@
<Label Content="Orientation:" DockPanel.Dock="Top" /> <Label Content="Orientation:" DockPanel.Dock="Top" />
<RadioButton Content="Auto" <RadioButton Content="Auto"
GroupName="Orientation" GroupName="Orientation"
IsChecked="{Binding $parent[controls:Connector].Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Auto}}" IsChecked="{Binding Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Auto}}"
DockPanel.Dock="Top" /> DockPanel.Dock="Top" />
<RadioButton Content="Horizontal" <RadioButton Content="Horizontal"
GroupName="Orientation" GroupName="Orientation"
IsChecked="{Binding $parent[controls:Connector].Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Horizontal}}" IsChecked="{Binding Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Horizontal}}"
DockPanel.Dock="Top" /> DockPanel.Dock="Top" />
<RadioButton Content="Vertical" <RadioButton Content="Vertical"
GroupName="Orientation" GroupName="Orientation"
IsChecked="{Binding $parent[controls:Connector].Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Vertical}}" IsChecked="{Binding Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Vertical}}"
DockPanel.Dock="Top" /> DockPanel.Dock="Top" />
</DockPanel> </DockPanel>
<Label Content="Offset:" DockPanel.Dock="Top" /> <Label Content="Offset:" DockPanel.Dock="Top" />
<TextBox Text="{Binding $parent[controls:Connector].Offset}" DockPanel.Dock="Top" /> <TextBox Text="{Binding Offset}" DockPanel.Dock="Top" />
</DockPanel> </DockPanel>
</Flyout> </Flyout>
</Setter.Value> </Setter.Value>

Просмотреть файл

@ -12,9 +12,9 @@
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<ItemsControl x:Name="PART_ConnectorsItemsControl" <ItemsControl x:Name="PART_ConnectorsItemsControl"
ItemsSource="{TemplateBinding ConnectorsSource}" ItemsSource="{Binding DrawingSource.Connectors, RelativeSource={RelativeSource TemplatedParent}}"
Width="{TemplateBinding Width}" Width="{Binding Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding Height}" Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}"
Background="Transparent" Background="Transparent"
IsHitTestVisible="False" IsHitTestVisible="False"
ClipToBounds="False"> ClipToBounds="False">
@ -29,7 +29,8 @@
StartPoint="{Binding Start, Converter={x:Static converters:PinToPointConverter.Instance}}" StartPoint="{Binding Start, Converter={x:Static converters:PinToPointConverter.Instance}}"
EndPoint="{Binding End, Converter={x:Static converters:PinToPointConverter.Instance}}" EndPoint="{Binding End, Converter={x:Static converters:PinToPointConverter.Instance}}"
Offset="{Binding Offset}" Offset="{Binding Offset}"
Orientation="{Binding Orientation}" /> Orientation="{Binding Orientation}"
ConnectorSource="{Binding .}" />
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>

Просмотреть файл

@ -12,17 +12,19 @@
<ControlTemplate> <ControlTemplate>
<Panel x:Name="PART_Panel" <Panel x:Name="PART_Panel"
Background="{TemplateBinding Background}"> Background="{TemplateBinding Background}">
<controls:GridDecorator EnableGrid="{TemplateBinding EnableGrid}" <controls:GridDecorator EnableGrid="{Binding DrawingSource.Settings.EnableGrid, RelativeSource={RelativeSource TemplatedParent}}"
GridCellWidth="{TemplateBinding GridCellWidth}" GridCellWidth="{Binding DrawingSource.Settings.GridCellWidth, RelativeSource={RelativeSource TemplatedParent}}"
GridCellHeight="{TemplateBinding GridCellHeight}" /> GridCellHeight="{Binding DrawingSource.Settings.GridCellHeight, RelativeSource={RelativeSource TemplatedParent}}" />
<controls:Connectors x:Name="PART_Connectors" <controls:Connectors x:Name="PART_Connectors"
Width="{TemplateBinding Width}" Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding Height}" Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
ConnectorsSource="{TemplateBinding ConnectorsSource}" /> DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}" />
<controls:Nodes x:Name="PART_Nodes" <controls:Nodes x:Name="PART_Nodes"
Width="{TemplateBinding Width}" Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding Height}" Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
NodesSource="{TemplateBinding NodesSource}" /> DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}"
InputSource="{Binding InputSource, RelativeSource={RelativeSource TemplatedParent}}"
AdornerCanvas="{Binding AdornerCanvas, RelativeSource={RelativeSource TemplatedParent}}" />
</Panel> </Panel>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>

Просмотреть файл

@ -12,7 +12,7 @@
<DockPanel> <DockPanel>
<!-- Snap --> <!-- Snap -->
<DockPanel DockPanel.Dock="Bottom"> <DockPanel DockPanel.Dock="Bottom">
<ToggleSwitch IsChecked="{TemplateBinding EnableSnap}" <ToggleSwitch IsChecked="{Binding EnableSnap, RelativeSource={RelativeSource TemplatedParent}}"
OnContent="Snap On" OnContent="Snap On"
OffContent="Snap Off" OffContent="Snap Off"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -30,7 +30,7 @@
Margin="4,4,2,4" Margin="4,4,2,4"
Padding="6" Padding="6"
TextAlignment="Left" TextAlignment="Left"
Text="{TemplateBinding SnapX}" /> Text="{Binding SnapX, RelativeSource={RelativeSource TemplatedParent}}" />
<Label Grid.Column="2" <Label Grid.Column="2"
Content="SY" Content="SY"
Margin="6,0,6,0" Margin="6,0,6,0"
@ -41,12 +41,12 @@
Margin="2,4,4,4" Margin="2,4,4,4"
Padding="6" Padding="6"
TextAlignment="Left" TextAlignment="Left"
Text="{TemplateBinding SnapY}" /> Text="{Binding SnapY, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid> </Grid>
</DockPanel> </DockPanel>
<!-- Grid --> <!-- Grid -->
<DockPanel DockPanel.Dock="Bottom"> <DockPanel DockPanel.Dock="Bottom">
<ToggleSwitch IsChecked="{TemplateBinding EnableGrid}" <ToggleSwitch IsChecked="{Binding EnableGrid, RelativeSource={RelativeSource TemplatedParent}}"
OnContent="Grid On" OnContent="Grid On"
OffContent="Grid Off" OffContent="Grid Off"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -64,7 +64,7 @@
Margin="4,4,2,4" Margin="4,4,2,4"
Padding="6" Padding="6"
TextAlignment="Left" TextAlignment="Left"
Text="{TemplateBinding GridCellWidth}" /> Text="{Binding GridCellWidth, RelativeSource={RelativeSource TemplatedParent}}" />
<Label Grid.Column="2" <Label Grid.Column="2"
Content="CH" Content="CH"
Margin="6,0,6,0" Margin="6,0,6,0"
@ -75,7 +75,7 @@
Margin="2,4,4,4" Margin="2,4,4,4"
Padding="6" Padding="6"
TextAlignment="Left" TextAlignment="Left"
Text="{TemplateBinding GridCellHeight}" /> Text="{Binding GridCellHeight, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid> </Grid>
</DockPanel> </DockPanel>
<!-- Width/Height --> <!-- Width/Height -->
@ -90,7 +90,7 @@
Margin="4,4,2,4" Margin="4,4,2,4"
Padding="6" Padding="6"
TextAlignment="Left" TextAlignment="Left"
Text="{TemplateBinding DrawingWidth}" /> Text="{Binding DrawingWidth, RelativeSource={RelativeSource TemplatedParent}}" />
<Label Grid.Column="2" <Label Grid.Column="2"
Content="H" Content="H"
Margin="6,0,6,0" Margin="6,0,6,0"
@ -101,7 +101,7 @@
Margin="2,4,4,4" Margin="2,4,4,4"
Padding="6" Padding="6"
TextAlignment="Left" TextAlignment="Left"
Text="{TemplateBinding DrawingHeight}" /> Text="{Binding DrawingHeight, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid> </Grid>
</DockPanel> </DockPanel>
</ControlTemplate> </ControlTemplate>

Просмотреть файл

@ -32,20 +32,21 @@
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"> HorizontalAlignment="Stretch">
<i:Interaction.Behaviors> <i:Interaction.Behaviors>
<idd:ContextDropBehavior Context="{TemplateBinding DataContext}"> <idd:ContextDropBehavior Context="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}">
<idd:ContextDropBehavior.Handler> <idd:ContextDropBehavior.Handler>
<behaviors:DrawingDropHandler RelativeTo="{Binding #PART_DrawingNode}" /> <behaviors:DrawingDropHandler DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}"
RelativeTo="{Binding #PART_DrawingNode}" />
</idd:ContextDropBehavior.Handler> </idd:ContextDropBehavior.Handler>
</idd:ContextDropBehavior> </idd:ContextDropBehavior>
</i:Interaction.Behaviors> </i:Interaction.Behaviors>
<Border Background="Transparent" <Border Background="Transparent"
Width="{TemplateBinding DrawingWidth}" Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding DrawingHeight}" Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
BoxShadow="4 11 30 1 #3F000000" BoxShadow="4 11 30 1 #3F000000"
ZIndex="-1"> ZIndex="-1">
<Panel Background="Transparent" <Panel Background="Transparent"
Width="{TemplateBinding DrawingWidth}" Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding DrawingHeight}"> Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}">
<Panel.Transitions> <Panel.Transitions>
<Transitions> <Transitions>
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.1" /> <TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.1" />
@ -53,56 +54,48 @@
</Panel.Transitions> </Panel.Transitions>
<controls:DrawingNode x:Name="PART_DrawingNode" <controls:DrawingNode x:Name="PART_DrawingNode"
Background="{DynamicResource DrawingBackground}" Background="{DynamicResource DrawingBackground}"
Width="{TemplateBinding DrawingWidth}" DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding DrawingHeight}" Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
NodesSource="{TemplateBinding NodesSource}" Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
ConnectorsSource="{TemplateBinding ConnectorsSource}" InputSource="{Binding ZoomControl, RelativeSource={RelativeSource TemplatedParent}}"
InputSource="{TemplateBinding ZoomControl}" AdornerCanvas="{Binding AdornerCanvas, RelativeSource={RelativeSource TemplatedParent}}"
AdornerCanvas="{TemplateBinding AdornerCanvas}"
EnableSnap="{TemplateBinding EnableSnap}"
SnapX="{TemplateBinding SnapX}"
SnapY="{TemplateBinding SnapY}"
EnableGrid="{TemplateBinding EnableGrid}"
GridCellWidth="{TemplateBinding GridCellWidth}"
GridCellHeight="{TemplateBinding GridCellHeight}"
ClipToBounds="False"> ClipToBounds="False">
<!-- TODO:
<controls:DrawingNode.ContextFlyout> <controls:DrawingNode.ContextFlyout>
<MenuFlyout> <MenuFlyout>
<MenuItem Header="Cu_t" <MenuItem Header="Cu_t"
Command="{Binding CutNodesCommand}" Command="{Binding DrawingSource.CutNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
InputGesture="{OnPlatform macOS=CMD+X, iOS=CMD+X, Default=Ctrl+X}"> InputGesture="{OnPlatform macOS=CMD+X, iOS=CMD+X, Default=Ctrl+X}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon Width="16" Height="16" Data="{DynamicResource EditorCutIcon}" /> <PathIcon Width="16" Height="16" Data="{DynamicResource EditorCutIcon}" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="_Copy" <MenuItem Header="_Copy"
Command="{Binding CopyNodesCommand}" Command="{Binding DrawingSource.CopyNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
InputGesture="{OnPlatform macOS=CMD+C, iOS=CMD+C, Default=Ctrl+C}"> InputGesture="{OnPlatform macOS=CMD+C, iOS=CMD+C, Default=Ctrl+C}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon Width="16" Height="16" Data="{DynamicResource EditorCopyIcon}" /> <PathIcon Width="16" Height="16" Data="{DynamicResource EditorCopyIcon}" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="_Paste" <MenuItem Header="_Paste"
Command="{Binding PasteNodesCommand}" Command="{Binding DrawingSource.PasteNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
InputGesture="{OnPlatform macOS=CMD+V, iOS=CMD+V, Default=Ctrl+V}"> InputGesture="{OnPlatform macOS=CMD+V, iOS=CMD+V, Default=Ctrl+V}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon Width="16" Height="16" Data="{DynamicResource EditorPasteIcon}" /> <PathIcon Width="16" Height="16" Data="{DynamicResource EditorPasteIcon}" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="D_uplicate" <MenuItem Header="D_uplicate"
Command="{Binding DuplicateNodesCommand}" Command="{Binding DrawingSource.DuplicateNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
InputGesture="{OnPlatform macOS=CMD+D, iOS=CMD+D, Default=Ctrl+D}" /> InputGesture="{OnPlatform macOS=CMD+D, iOS=CMD+D, Default=Ctrl+D}" />
<MenuItem Header="-" /> <MenuItem Header="-" />
<MenuItem Header="Select _All" <MenuItem Header="Select _All"
Command="{Binding SelectAllNodesCommand, FallbackValue={x:Null}}" Command="{Binding DrawingSource.SelectAllNodesCommand, RelativeSource={RelativeSource TemplatedParent}, FallbackValue={x:Null}}"
InputGesture="{OnPlatform macOS=CMD+A, iOS=CMD+A, Default=Ctrl+A}" /> InputGesture="{OnPlatform macOS=CMD+A, iOS=CMD+A, Default=Ctrl+A}" />
<MenuItem Header="De_select All" <MenuItem Header="De_select All"
Command="{Binding DeselectAllNodesCommand, FallbackValue={x:Null}}" Command="{Binding DrawingSource.DeselectAllNodesCommand, RelativeSource={RelativeSource TemplatedParent}, FallbackValue={x:Null}}"
InputGesture="Escape" /> InputGesture="Escape" />
<MenuItem Header="-" /> <MenuItem Header="-" />
<MenuItem Header="_Delete" <MenuItem Header="_Delete"
Command="{Binding DeleteNodesCommand}" Command="{Binding DrawingSource.DeleteNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
InputGesture="Delete"> InputGesture="Delete">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon Width="16" Height="16" Data="{DynamicResource DeleteIcon}" /> <PathIcon Width="16" Height="16" Data="{DynamicResource DeleteIcon}" />
@ -110,12 +103,11 @@
</MenuItem> </MenuItem>
</MenuFlyout> </MenuFlyout>
</controls:DrawingNode.ContextFlyout> </controls:DrawingNode.ContextFlyout>
-->
</controls:DrawingNode> </controls:DrawingNode>
<Canvas x:Name="PART_AdornerCanvas" <Canvas x:Name="PART_AdornerCanvas"
Background="Transparent" Background="Transparent"
Width="{TemplateBinding DrawingWidth}" Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding DrawingHeight}" Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
</Panel> </Panel>
</Border> </Border>

Просмотреть файл

@ -9,8 +9,8 @@
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Panel Width="{TemplateBinding Width}" <Panel Width="{Binding NodeSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding Height}"> Height="{Binding NodeSource.Height, RelativeSource={RelativeSource TemplatedParent}}">
<ContentPresenter x:Name="PART_ContentPresenter" <ContentPresenter x:Name="PART_ContentPresenter"
Background="{TemplateBinding Background}" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
@ -23,9 +23,9 @@
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" /> VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
<controls:Pins x:Name="PART_Pins" <controls:Pins x:Name="PART_Pins"
Width="{TemplateBinding Width}" Width="{Binding NodeSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding Height}" Height="{Binding NodeSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
PinsSource="{TemplateBinding PinsSource}"/> NodeSource="{Binding NodeSource, RelativeSource={RelativeSource TemplatedParent}}"/>
</Panel> </Panel>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>

Просмотреть файл

@ -13,22 +13,18 @@
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<ItemsControl x:Name="PART_NodesItemsControl" <ItemsControl x:Name="PART_NodesItemsControl"
ItemsSource="{TemplateBinding NodesSource}" ItemsSource="{Binding DrawingSource.Nodes, RelativeSource={RelativeSource TemplatedParent}}"
Width="{TemplateBinding Width}" Width="{Binding Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding Height}" Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}"
Background="Transparent" Background="Transparent"
ClipToBounds="False"> ClipToBounds="False">
<i:Interaction.Behaviors> <i:Interaction.Behaviors>
<behaviors:NodesSelectedBehavior /> <behaviors:NodesSelectedBehavior DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}" />
<!-- TODO: Fix using $parent[controls:DrawingNode] --> <behaviors:DrawingSelectionBehavior DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}"
<behaviors:DrawingSelectionBehavior InputSource="{Binding $parent[controls:DrawingNode].InputSource}" InputSource="{Binding InputSource, RelativeSource={RelativeSource TemplatedParent}}"
AdornerCanvas="{Binding $parent[controls:DrawingNode].AdornerCanvas}" AdornerCanvas="{Binding AdornerCanvas, RelativeSource={RelativeSource TemplatedParent}}" />
EnableSnap="{Binding $parent[controls:DrawingNode].EnableSnap}" <behaviors:DrawingPressedBehavior DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}" />
SnapX="{Binding $parent[controls:DrawingNode].SnapX}" <behaviors:DrawingMovedBehavior DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}" />
SnapY="{Binding $parent[controls:DrawingNode].SnapY}"
x:CompileBindings="False" />
<behaviors:DrawingPressedBehavior />
<behaviors:DrawingMovedBehavior />
</i:Interaction.Behaviors> </i:Interaction.Behaviors>
<ItemsControl.Styles> <ItemsControl.Styles>
<Style Selector="ItemsControl > ContentPresenter" x:DataType="m:INode"> <Style Selector="ItemsControl > ContentPresenter" x:DataType="m:INode">
@ -47,7 +43,7 @@
Content="{Binding Content}" Content="{Binding Content}"
Width="{Binding Width}" Width="{Binding Width}"
Height="{Binding Height}" Height="{Binding Height}"
PinsSource="{Binding Pins}" /> NodeSource="{Binding .}" />
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>

Просмотреть файл

@ -13,8 +13,8 @@
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Ellipse x:Name="PART_Pin" <Ellipse x:Name="PART_Pin"
Width="{TemplateBinding Width}" Width="{Binding Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding Height}" /> Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>

Просмотреть файл

@ -13,9 +13,9 @@
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<ItemsControl x:Name="PART_PinsItemsControl" <ItemsControl x:Name="PART_PinsItemsControl"
ItemsSource="{TemplateBinding PinsSource}" ItemsSource="{Binding NodeSource.Pins, RelativeSource={RelativeSource TemplatedParent}}"
Width="{TemplateBinding Width}" Width="{Binding NodeSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{TemplateBinding Height}" Height="{Binding NodeSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
ClipToBounds="False"> ClipToBounds="False">
<ItemsControl.Styles> <ItemsControl.Styles>
<Style Selector="ItemsControl > ContentPresenter" x:DataType="m:IPin"> <Style Selector="ItemsControl > ContentPresenter" x:DataType="m:IPin">
@ -44,7 +44,8 @@
Width="{Binding Width}" Width="{Binding Width}"
Height="{Binding Height}" Height="{Binding Height}"
Alignment="{Binding Alignment}" Alignment="{Binding Alignment}"
Id="{Binding Name}" /> Id="{Binding Name}"
PinSource="{Binding .}"/>
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>

Просмотреть файл

@ -14,7 +14,7 @@
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<ListBox ItemsSource="{TemplateBinding TemplatesSource}" <ListBox ItemsSource="{Binding TemplatesSource, RelativeSource={RelativeSource TemplatedParent}}"
Background="Transparent"> Background="Transparent">
<ListBox.Resources> <ListBox.Resources>
<behaviors:TemplatesListBoxDropHandler x:Key="TemplatesListBoxDropHandler" /> <behaviors:TemplatesListBoxDropHandler x:Key="TemplatesListBoxDropHandler" />
@ -28,7 +28,7 @@
<i:BehaviorCollectionTemplate> <i:BehaviorCollectionTemplate>
<i:BehaviorCollection> <i:BehaviorCollection>
<idd:ContextDragBehavior /> <idd:ContextDragBehavior />
<behaviors:InsertTemplateOnDoubleTappedBehavior Drawing="{Binding $parent[Toolbox].Drawing}" /> <behaviors:InsertTemplateOnDoubleTappedBehavior />
</i:BehaviorCollection> </i:BehaviorCollection>
</i:BehaviorCollectionTemplate> </i:BehaviorCollectionTemplate>
</Setter> </Setter>
@ -42,7 +42,7 @@
Content="{Binding Content}" Content="{Binding Content}"
Width="{Binding Width}" Width="{Binding Width}"
Height="{Binding Width}" Height="{Binding Width}"
PinsSource="{Binding Pins}"> NodeSource="{Binding .}">
<controls:Node.Styles> <controls:Node.Styles>
<Style Selector="controls|Pins /template/ ItemsControl#PART_PinsItemsControl"> <Style Selector="controls|Pins /template/ ItemsControl#PART_PinsItemsControl">
<Setter Property="IsVisible" Value="False" /> <Setter Property="IsVisible" Value="False" />