Strange scrolling behavior

I do not understand your code. There is no Nodes property on ILinksModel or GraphLinksModel. And clearly you have additional methods on this PlanModel.

Which properties/attributes have you set/bound on your Diagram, and to what values? What about event handlers or method overrides?

Yes you are right. Sorry for my mistake. Its a ViewModel which has two properties:
public ObservableCollection Links { get; private set; }

    public ObservableCollection<DiagramItemModelBase> Nodes { get; private set; }

They are binded to IDiagramModel.NodesSource and IDiagramModel.LinksSource.

OK, so they are just collections of data.

What about Diagram property settings and event handlers?

Diagram XAML properties:

           AllowRelink="True"
            AllowLink="True" 
            AllowDrop="True"
            AllowScroll="True"
            AllowZoom="True"
            Padding="80, 30, 30, 30"
            VerticalContentAlignment="Top"
            HorizontalContentAlignment="Left"

Initialization in CommandHandler :

   protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);
        Diagram.UnloadingClearsPartManager = false;
        Diagram.SelectionMoved += DiagramSelectionMoved;
        Diagram.NodeResized += Diagram_NodeResized;
        Diagram.PreviewMouseDoubleClick += DiagramPreviewMouseDoubleClick;
        Diagram.LinkReshaped += DiagramLinkReshaped;
        Diagram.LinkRelinked += DiagramLinkRelinked;
        Diagram.MouseRightButtonUp += DiagramMouseRightButtonUp;
        Diagram.MouseRightButtonDown += DiagramOnMouseRightButtonDown;
        Diagram.MouseLeftButtonUp += DiagramOnMouseLeftButtonDownEvent;
        Diagram.MouseMove += DiagramOnMouseMove;
        Diagram.AllowCopy = false;
        Diagram.DragSelectingTool.Delay = 0;
    }

And - as I mentioned it before, before the update transaction:

    Diagram.LayoutCompleted += DoOnLayoutComplete;

and in this event handler:

    private void DoOnLayoutComplete(object sender, DiagramEventArgs e)
    {
        Diagram.LayoutCompleted -= DoOnLayoutComplete;
        foreach (Link link in Diagram.Links)
        {
            var d = link.Data as ConfigLinkDiagramModel;
            if (d == null || d.Points == null) continue;
            link.Route.Points = d.Points.ToList();
        }
    }

We update link routes.

What do DiagramOnMouseLeftButtonDownEvent and DiagramOnMouseMove do?

Are there any handled exceptions that occur?

These methods are used for copy-paste tasked functions. But they are try…catched and I tested them. There are no exceptions in there in runtime when loading the diagram.

Is there any method to repaint the diagram after it renders the first time?

I still do not understand the cause of the problem.

I suppose you could implement a Diagram.InitialLayoutCompleted handler that calls Begin
Invoke
on an action that calls Diagram.Panel.UpdateDiagramBounds(). But I am not entirely confident that will help.

Have you set any properties or event handlers on the DiagramPanel? Have you specified a Diagram.Template or fiddled with the ScrollViewer?

Ok, so we do not use any methods or events from DiagramPanel. And there are no ScrollViewers or Templates for the Diagram itself. We have only made templates for nodes and links.

I have tried to run UpdateDiagramBounds on InitialLayoutComplete, also with a special delay - but this does not help as you said:

private void DiagramOnInitialLayoutCompleted(object sender,

     DiagramEventArgs e)
    {
        Task.Run(() =>
        {
            Thread.Sleep(1500);
            var act = new Action(() =>
            {
                Diagram.Panel.UpdateDiagramBounds();
            });
            Dispatcher.BeginInvoke(act);
        });
    }

There is a small issue also, when rendering the largest nodes. After the diagram appears, in some cases these big nodes are not visible. After the use of scrolls (vertical or horizontal) big nodes appear. I have checked, that we do not make any Diagram changes at that perdiod of time. Maybe these two things are connected?

The last behavior you describe is also very suspicious. You might want to check, at least for those large nodes, whether their Node.Bounds matches the bounds that they should have before and after they show up after scrolling.

Ok. I try to check that.

Yes. I’ve checked it.
After thie diagram is initialized, this specific node has bounds:
{-784;2431,04;130;63,92}
After scrolling down, this node appears with new bounds:
{-784;1315,08;130;2295,84}

I’ve checked that, and we are binding only Location from ViewModel. Width and Height are set from the node template.

Normally, scrolling (or panning) and zooming (or scaling) the diagram will have no effect on any Node or Link’s bounds, which are always in model coordinates. This makes scrolling and zooming very fast.

So you must have implemented some behavior to change some nodes’ bounds. That is usually done in a DiagramPanel.ViewportBoundsChanged event handler. Do you have such a handler? Or what customizations have you done with your DiagramPanel, i.e. the value of Diagram.Panel after the ControlTemplate has been applied to the Diagram control?

I have double checked. None of these operations we make. We don’t use in any place in code Diagram.Panel property.

I cannot explain that odd behavior. Is there any way for me to reproduce the problem?

I will prepare a sample app next week for you to reproduce this problem.

It might be sufficient to give me the node template for the node whose bounds changed magically during the scroll.

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>

That is complicated. Still, almost all of it is details about the internals of the node, which should have no effect on the position or size of the whole node. Remember, the problem is that somehow the node’s Y position and height changed without the diagram’s DiagramPanel getting the chance to update its http://goxam.com/3.0/apiCore/index.html#Northwoods.GoWPF~Northwoods.GoXam.DiagramPanel~DiagramBounds.html.

So the obvious unknown is what is happening in your UserControl. What does it do? Can you determine that its position and height are changing during scrolling?

Yes it is. After trying out - I think everything - I made a simple workaround with:

private void DiagramOnInitialLayoutCompleted(object sender, DiagramEventArgs e)
    {
        Task.Run(async () =>
        {
            await Task.Delay(100);
            new WpfContext().BeginInvoke(() =>
            {
                Diagram.Padding = new Thickness(80, 130, 30, 130);
            });
        });
    }

Changing Padding property fixes the problem - before any scroll operation. Original Padding value in xaml is 80, 30, 30, 30.

I’m glad you found a solution, but I don’t see how that could be a real solution.

At first I misread what you wrote and thought you were setting DiagramPanel.Padding, which would cause the DiagramPanel.DiagramBounds to be recomputed.

But your setting of Diagram.Padding really doesn’t affect the contents of the diagram at all.

And I don’t see why doing this on Diagram.InitialLayoutCompleted solves the problem after the user has made some changes to the diagram.