Binding Inconsistency

I am confused by the fact that my Binding works for the ToolTip’s TextBlock’s value, but not the ContextMenu’s TextBlock’s values. The following is inside a LinkTemplate. The Binding in the ToolTip to Data.LinkOutputValue works fine. It is the TextBlock within the ContextMenu that will not update. I want the value to persist on the screen and update if the value changes. Please help. Do I have to raise the property changed again for the other two TextBlocks??

    <TextBlock x:Name="ValueLabelLeft" Text="{Binding Data.LinkOutputValue, Mode=OneWay}" go:LinkPanel.Index="0" go:LinkPanel.Offset="NaN NaN"
                 TextWrapping="Wrap" TextAlignment="Center" FontWeight="Bold" FontSize="14"
                 Visibility="{Binding Data.ShowValue, Converter={StaticResource booleanToVisibilityConverter}}">
      </TextBlock>
      <TextBlock x:Name="ValueLabelRight" Text="{Binding Data.LinkOutputValue, Mode=OneWay}"  go:LinkPanel.Index="-1" go:LinkPanel.Offset="NaN NaN"
                 TextWrapping="Wrap" TextAlignment="Center" FontWeight="Bold" FontSize="14"
                 Visibility="{Binding Data.ShowValue, Converter={StaticResource booleanToVisibilityConverter}}">
      </TextBlock>
      <go:LinkPanel.ToolTip>
        <TextBlock Text="{Binding Data.LinkOutputValue}" FontWeight="Bold" FontSize="14"/>
      </go:LinkPanel.ToolTip>
      <go:LinkPanel.ContextMenu>
        <ContextMenu x:Name="LinkContextMenu"
                         Background="{StaticResource GradientLightGray}"
                         Foreground="{StaticResource TextLinkBrush}"
                         ItemsPanel="{StaticResource ContextMenuItemsPanelTemplate}"
                         Padding="-1">
          <MenuItem Command="{Binding Data.ShowValueCommand}"
                        Header="Show Value or Error"
                        ToolTip="Show Value or Error if signal is in error." />
        </ContextMenu>
      </go:LinkPanel.ContextMenu>

I haven’t noticed any problems with binding in ContextMenu MenuItems.

If you change your MenuItem Header to be:
Header="{Binding Data.LinkOutputValue}"
does the menu show the expected text?

This doesn’t work. I changed to:

        <ContextMenu x:Name="LinkContextMenu"
                         Background="{StaticResource GradientLightGray}"
                         Foreground="{StaticResource TextLinkBrush}"
                         ItemsPanel="{StaticResource ContextMenuItemsPanelTemplate}"
                         Padding="-1">
          <MenuItem Command="{Binding Data.ShowValueCommand}"
                        Header="{Binding Data.LinkOutputValue}"
                        ToolTip="Show Value or Error if signal is in error." />
        </ContextMenu>

And, the value is now in the menu item header which doesn’t update. The textblocks on the link do not update either. However the tooltip still updates. Any other ideas?

Oh, so the problem isn’t that the MenuItems isn’t showing the proper text the first time, but only when showing the context menu the second and succeeding times when bringing up the context menu on other nodes?

Why aren’t you using ContextMenuService.ContextMenu? Maybe that would cause the ContextMenu to be updated.

A ContextMenuService appears to not be attachable to a LinkPanel…

Let me try to explain what I am trying to do. There are nodes on a ‘canvas’ in which we are linking together. On the link, we have a value being sent from one to the other. This value I want displayed on each end of the link if the user right clicks and chooses to display the values. After displaying the values and then changing the value, the tooltip displays the correct value but the TextBlocks do not.

<go:LinkPanel go:Part.Copyable=“False”
go:Part.Deletable="{Binding Data.IsDeletable}"
go:Part.Reshapable=“True”
go:Part.Selectable="{Binding Data.IsSelectable}"
go:Part.SelectionAdorned=“True”
go:Part.SelectionAdornmentTemplate="{StaticResource LinkSelectionAdornmentTemplate}">
go:Link.Route
<go:Route Curve=“None”
FromEndSegmentLength=“30”
ToEndSegmentLength=“30”
ToShortLength=“2”
LinkReshapeHandleTemplate="{StaticResource LinkReshapeHandleTemplate}"
RelinkableFrom=“False”
RelinkableTo=“False”
Routing=“AvoidsNodes”
Margin=“2” />
</go:Link.Route>
<go:LinkShape Stroke=“Transparent” StrokeThickness=“8” />
<go:LinkShape x:Name=“Path”
Fill="{Binding Data.LinkColor}"
Stroke="{Binding Data.LinkColor}"
StrokeThickness=“2.5” />





go:LinkPanel.ToolTip

</go:LinkPanel.ToolTip>
go:LinkPanel.ContextMenu



</go:LinkPanel.ContextMenu>
</go:LinkPanel>

Try calling Link.Remeasure() when you modify the data upon which the Link is bound.

Does Link.Remeasure() get called normally when moving a node and the link ‘redraws’?

Yes, the effects of Part.Remeasure() occur naturally when many changes are made.
However, the measurement and arrangement of Links is different than for Nodes, mostly for efficiency reasons.
It’s also slightly different between WPF and Silverlight. Are you using WPF?

Yes, we are using WPF and a GraphLinksModel.

I got it to work. I am forcing it to update even the value has already been updated using a listener. This seems to be a workaround and I am thinking there is probably a better way. However, it is working now. Thanks for your help!

I would like to access the Remeasure() method like you suggested as my workaround seems to me to be a hack. However, I am not able to access it. I have addressability to the NodeData. How do I get to the Node from the NodeData?

Part.Remeasure() is public, so you should be able to call it. But why are you asking about getting a Node from some node data object? The previous discussion was about Links and how they are measured and arranged differently from regular FrameworkElements including Nodes. You should not need to call Node.Remeasure().

Still, if you are asking about Nodes, there might be more than one Node for a node data object in a model, because there might be multiple Diagrams displaying one model. You need access to the Diagram(s), so that you can call Diagram.PartManager.FindNodeForData.

I was finally able to call Link.Remeasure()! Thanks. I have another question related to this post. As you know from above, we are trying to show output values on the links. In one senario, we have 4 links coming out of a node and the values are showing on each end of the line in text blocks and I am using a boolean converter to decide whether to show them or not. It seems whenever I reload the screen, the 4 values on the left are slightly on top of each other. I was wondering if there was an easier way and better way to not allow text blocks values to overlay each other - only show one? I know that I can change the background of the text block to match our background, but then when the node is moved around, the text block shows.

You haven’t shown a screenshot of the problem, so I can only guess what might be going on.

You could try positioning the labels a bit further from the ends. You’ll have to experiment, but you could try setting the go:LinkPanel.Index=“1” and “-2”, respectively, and maybe change the go:LinkPanel.Offset too.

Above is what the text blocks look like, the value is shown 4 times (0%) and they are just off a bit. We only want one value to show on the side of the link. Maybe if they were overlayed exactly, it might not be as bad. I will play around with the offsets.

Oh, that’s because you are using Spot.RightSide (or something like that) as the FromSpot. That causes the links to be spread out, avoiding overlapping segments at the port.

However, with small ports, spreading out the link connection points does not make sense since they cannot be separated enough from each other. I would just use Spot.MiddleRight, if I were you, in this circumstance.

Of course that only helps with the legibility of the text label if all N labels have the same text. If they might have different ones, you’ll need to attach them elsewhere, by setting go:LinkPanel.Index and maybe go:LinkPanel.Fraction too.

I changed the FromSpot to MiddleRight and it appears to be the same. The values will always be the same coming out of the same output.

Perhaps you are using a DiagramLayout that ignores the port’s Spot values. Try setting …Layout.SetsPortSpots = false, although the name(s) of the property(ies) varies with the kind of DiagramLayout it is.

Alternatively, include the FromSpot in your Link DataTemplate.

Will this get the links to all come out together and then break off when they need to? I think if I can get those links to be on top of each other, the text blocks will as well. I am unsure where to add Layout.SetPortSpots, I have tried several places in within the diagram tags. I also added the FromSpot to the link template and this does not work.

Look at the documentation for the particular layout that you are using to see what the property is or properties are.