Ok, this is our node user control:
<UserControl x:Class="Vision20.ConfigGui.Views.Documents.LogicConfig.ConfigNodeView"
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:go="http://schemas.nwoods.com/GoXam"
xmlns:logicConfig="clr-namespace:Vision20.ConfigGui.Views.Documents.LogicConfig"
xmlns:port="clr-namespace:Vision20.ConfigGui.Views.Documents.Port"
xmlns:documents="clr-namespace:Vision20.ConfigGui.Views.Documents"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
d:DesignHeight="50" d:DesignWidth="130"
d:DataContext="{d:DesignInstance {x:Type go:Node}}"
Width="130"
x:Name="CurrentControl"
go:Node.Location="{Binding Path=Data.(documents:NodeDiagramModel.Location), Mode=TwoWay, UpdateSourceTrigger=Explicit}"
go:Node.LocationSpot="Center">
<UserControl.Resources>
<logicConfig:BooleanToVisibilityHiddenNegationConverter x:Key="BooleanToVisibilityHiddenNegationConverter" />
<documents:BoolInvertedToGridRowHeightConverter x:Key="BoolToGridRowHeight"></documents:BoolInvertedToGridRowHeightConverter>
</UserControl.Resources>
<go:NodePanel ToolTipService.ShowDuration="60000">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown" x:Uid="ML_0175">
<i:InvokeCommandAction Command="{Binding Path=Data.(documents:NodeDiagramModel.HandleNodeClickCommand)}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<go:NodePanel.ToolTip>
<StackPanel Orientation="Vertical" MaxWidth="300" MaxHeight="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition />
<RowDefinition Height="{Binding Path= Data.(documents:NodeDiagramModel.IsValidLogicController), Converter={StaticResource BoolToGridRowHeight}}" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Path=Data.(documents:NodeDiagramModel.Name)}" TextWrapping="Wrap" />
<TextBlock Grid.Row="1" Text="{Binding Path=Data.(documents:NodeDiagramModel.NodeId), StringFormat=ID: {0}}" />
<TextBlock Grid.Row="2" Text="{Binding Path=Data.(documents:NodeDiagramModel.Description), StringFormat={}{0}}" TextTrimming="WordEllipsis" TextWrapping="Wrap"
Visibility="{Binding Path= Data.(documents:NodeDiagramModel.IsClosed), Converter={StaticResource BooleanToVisibilityHiddenNegationConverter}}" />
<TextBlock Grid.Row="3" Text="{x:Static logicConfig:NodeIconNameHelper.Info}" FontStyle="Oblique" x:Uid="ML_0186"></TextBlock>
</Grid>
</StackPanel>
</go:NodePanel.ToolTip>
<Grid go:Node.Avoidable="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="22" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Node name -->
<TextBlock Grid.Row="0" Foreground="Black" Text="{Binding Path=Data.(documents:NodeDiagramModel.Name)}"
Visibility="{Binding Path=Data.(documents:NodeDiagramModel.IsClosed), Converter={StaticResource BooleanToVisibilityHiddenNegationConverter}}"
TextAlignment="Center" TextWrapping="Wrap" Height="Auto" MinHeight="0" Margin="4" />
<!-- Control frame -->
<Border Grid.Row="1" CornerRadius="10">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="2" x:Uid="ML_0194" />
<Setter Property="BorderBrush" Value="Black" x:Uid="ML_0195" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="AliceBlue" Offset="0.0" />
<GradientStop Color="LightBlue" Offset="1.0" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Part.IsSelected}" Value="True" x:Uid="ML_0200">
<Setter Property="Border.Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="10" RenderingBias="Performance" ShadowDepth="0" Color="DarkSalmon" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsEnabled)}" Value="False" x:Uid="ML_0203">
<Setter Property="Border.Opacity" Value="0.34" x:Uid="ML_0204" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsMarked)}" Value="True" x:Uid="ML_0205">
<Setter Property="Border.Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="25" RenderingBias="Performance" ShadowDepth="0" Color="Magenta" />
</Setter.Value>
</Setter>
<DataTrigger.EnterActions>
<BeginStoryboard Name="BlinkAnimation">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0.1" AutoReverse="True" Duration="0:0:0.5" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="BlinkAnimation" x:Uid="ML_0211" />
</DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsValidLogicController)}" Value="False" x:Uid="ML_0212">
<Setter Property="Background">
<Setter.Value>
<DrawingBrush TileMode="Tile"
Viewport="0,0,30,30" ViewportUnits="Absolute"
Viewbox="0,0,30,30" ViewboxUnits="Absolute">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Pen>
<Pen Brush="#ff7bd5ff" Thickness="10" />
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<Geometry>M0,0 L30,30 M15,-15 L45,15 M-15,15 L15,45</Geometry>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="AliceBlue" />
<GradientStop Offset="1.0" Color="LightBlue" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<!-- Control main grid - margin-2 because of border -->
<Grid Margin="-2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Type name -->
<TextBlock Text="{Binding Path=Data.(documents:NodeDiagramModel.ReadableFamily)}" Grid.Row="0" Foreground="Black" TextAlignment="Center" Height ="Auto" TextWrapping="Wrap" Margin="10,2,10,2"
FontWeight="Bold" />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<ItemsControl Grid.Column="0" ItemsSource="{Binding Path=Data.(documents:NodeDiagramModel.InputPorts)}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- Input template -->
<Grid Margin="0,5,0,5">
<Grid.RowDefinitions>
<!-- Pin -->
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<!-- Pin graphics -->
<ColumnDefinition Width="10" />
<!-- Pin name -->
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Pin graphics -->
<port:PortControl Grid.Row="0" Grid.Column="0" />
<!-- Pin name -->
<TextBlock Foreground="Black" Grid.Row="0" Grid.Column="1" Text="{Binding Name}"
VerticalAlignment="Center" Margin="5,0,5,0" FontSize="10" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" Height="Auto" FontWeight="Bold" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Output pins -->
<ItemsControl Grid.Column="1" ItemsSource="{Binding Path=Data.(documents:NodeDiagramModel.OutputPorts)}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,5,0,5">
<Grid.RowDefinitions>
<!-- Pin -->
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<!-- Pin name -->
<ColumnDefinition Width="*" />
<!-- Pin graphics -->
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<!-- Pin name -->
<TextBlock Grid.Row="0" Grid.Column="0" Foreground="Black" Text="{Binding Name}" VerticalAlignment="Center" TextAlignment="Right" Margin="5,0,-5,0" FontSize="10" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" Height="Auto" FontWeight="Bold" />
<!-- Pin graphics -->
<port:PortControl Margin="8,0,-8,0" Grid.Row="0" Grid.Column="1" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
<Grid Grid.Row="2" Height="20">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="1" Width="10" Height="10" HorizontalAlignment="Right" Fill="Gray" Margin="5" Stroke="Black" StrokeThickness="1" />
</Grid>
<Border Grid.Row="0" Margin="10,0,0,0" Grid.RowSpan="3" Background="Transparent" Visibility="{Binding Path=Data.(documents:NodeDiagramModel.IsClosed), Converter={StaticResource BooleanToVisibilityHiddenNegationConverter}}" />
</Grid>
</Border>
</Grid>
</go:NodePanel>
</UserControl>
And templates definitions:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:go="http://schemas.nwoods.com/GoXam"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:logicConfig="clr-namespace:Vision20.ConfigGui.Views.Documents.LogicConfig"
xmlns:commands="clr-namespace:Vision20.ConfigGui.Commands"
xmlns:documents="clr-namespace:Vision20.ConfigGui.Views.Documents"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d">
<system:Boolean x:Key="True">True</system:Boolean>
<system:Boolean x:Key="False">False</system:Boolean>
<logicConfig:ModelToInputPinWorkspaceDataConverter x:Key="ModelToInputPinWorkspaceDataConverter" />
<logicConfig:ModelToOutputPinWorkspaceDataConverter x:Key="ModelToOutputPinWorkspaceDataConverter" />
<logicConfig:BooleanToVisibilityHiddenNegationConverter x:Key="InvertBooleanToVisibilityConverter" />
<DataTemplate x:Key="InputPinManagementAdornmentTemplate">
<Grid go:Node.LocationElementName="Main">
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsClosed)}"
Value="True" x:Uid="ML_0112">
<Setter Property="Margin" Value="-6,-14,0,0" x:Uid="ML_0113" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsClosed)}"
Value="False" x:Uid="ML_0114">
<Setter Property="Margin" Value="-6,-28,0,0" x:Uid="ML_0115" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Button Padding="0" Command="{x:Static commands:PinCommands.ManagePinsAmount}"
CommandParameter="{Binding Path=Data,Converter={StaticResource ModelToInputPinWorkspaceDataConverter}}"
Width="44" Height="34" Margin="1" Background="Transparent" BorderBrush="Transparent">
<StackPanel>
<Image Source="/Views/Documents/LogicConfig/pin_add_remove.png" />
</StackPanel>
</Button>
</StackPanel>
<go:SpotPanel x:Name="Main" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="InputOutputPinManagementAdornmentTemplate">
<Grid go:Node.LocationElementName="Main">
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Center">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsClosed)}"
Value="True" x:Uid="ML_0124">
<Setter Property="Margin" Value="0,-14,0,0" x:Uid="ML_0125" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsClosed)}"
Value="False" x:Uid="ML_0126">
<Setter Property="Margin" Value="0,-28,0,0" x:Uid="ML_0127" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Button Padding="0" Command="{x:Static commands:PinCommands.ManagePinsAmount}"
CommandParameter="{Binding Path=Data,Converter={StaticResource ModelToInputPinWorkspaceDataConverter}}"
Width="44" Height="34" Margin="1" Background="Transparent" BorderBrush="Transparent">
<StackPanel>
<Image Source="/Views/Documents/LogicConfig/pin_add_remove.png" />
</StackPanel>
</Button>
</StackPanel>
<go:SpotPanel x:Name="Main" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="OutputPinManagementAdornmentTemplate">
<Grid go:Node.LocationElementName="Main">
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsClosed)}"
Value="True" x:Uid="ML_0136">
<Setter Property="Margin" Value="0,-14,-6,0" x:Uid="ML_0137" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Data.(documents:NodeDiagramModel.IsClosed)}"
Value="False" x:Uid="ML_0138">
<Setter Property="Margin" Value="0,-28,-6,0" x:Uid="ML_0139" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Button Padding="0" Command="{x:Static commands:PinCommands.ManagePinsAmount}"
CommandParameter="{Binding Path=Data,Converter={StaticResource ModelToOutputPinWorkspaceDataConverter}}"
Width="44" Height="34" Margin="1" Background="Transparent" BorderBrush="Transparent">
<StackPanel>
<Image Source="/Views/Documents/LogicConfig/pin_add_remove.png" />
</StackPanel>
</Button>
</StackPanel>
<go:SpotPanel x:Name="Main" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="DefaultNodeTemplate" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView />
</DataTemplate>
<go:DataTemplateDictionary x:Key="ConfigNodeTemplateStore" Default="{StaticResource DefaultNodeTemplate}">
<DataTemplate x:Key="Note" DataType="{x:Type go:Part}">
<Grid x:Name="NoteGrid" go:Part.SelectionElementName="Shape" go:Part.SelectionAdorned="True"
Background="Transparent"
go:Part.Resizable="True" go:Part.Text="{Binding Path=Data}"
go:Node.Location="{Binding Path=Data.(logicConfig:ConfigNoteDataModel.Location), Mode=TwoWay, UpdateSourceTrigger=Explicit}"
Width="{Binding Path=Data.(logicConfig:ConfigNoteDataModel.NodeWidth), Mode=TwoWay}"
Height="{Binding Path=Data.(logicConfig:ConfigNoteDataModel.NodeHeight), Mode=TwoWay}"
Cursor="Hand">
<go:NodePanel x:Name="parentElementName" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<go:NodeShape x:Name="Shape" go:NodePanel.Figure="TransmittalTape" Stroke="Black"
StrokeThickness="3"
Fill="{Binding Path=Data.(logicConfig:ConfigNoteDataModel.Color), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
MinWidth="120" MinHeight="100" MaxHeight="800" MaxWidth="800"
Width="{Binding Path=Data.(logicConfig:ConfigNoteDataModel.NodeWidth), Mode=TwoWay}"
Height="{Binding Path=Data.(logicConfig:ConfigNoteDataModel.NodeHeight), Mode=TwoWay}" IsHitTestVisible="False" />
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="5,5,5,5" Cursor="Pen" IsHitTestVisible="False">
<Grid IsHitTestVisible="False">
<xctk:RichTextBox
IsReadOnly="true" IsDocumentEnabled="True"
Cursor="Arrow" BorderThickness="0" VerticalAlignment="Stretch" Background="Transparent"
x:Name="_richTextBox"
IsHitTestVisible="False"
Text="{Binding Path=Data.(logicConfig:ConfigNoteDataModel.NoticeText), Mode=TwoWay}">
<xctk:RichTextBox.TextFormatter>
<xctk:RtfFormatter />
</xctk:RichTextBox.TextFormatter>
</xctk:RichTextBox>
</Grid>
</ScrollViewer>
</go:NodePanel>
</Grid>
</DataTemplate>
<DataTemplate x:Key="BinaryConverterBinDec" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="BinaryConverterDecBin" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource OutputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="BooleanClosedOr" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="BooleanClosedAnd" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="SwitchSEL" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputOutputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="MathematicalClosedSum" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="MathematicalClosedProduct" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="InputSelector" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="OutputSelector" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource OutputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="TextFormatter" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputPinManagementAdornmentTemplate}" />
</DataTemplate>
<DataTemplate x:Key="Filter" DataType="{x:Type go:Part}">
<logicConfig:ConfigNodeView go:Part.SelectionAdorned="True"
go:Part.SelectionAdornmentTemplate="{StaticResource InputOutputPinManagementAdornmentTemplate}" />
</DataTemplate>
</go:DataTemplateDictionary>
</ResourceDictionary>