I’m seeing something strange with GoXam for WPF 1.3.5. I have a Diagram that is observed by an Overview. Whenever the Diagram is resized, the Overview stops displaying data. The purple indicator box is gone and no matter how much I scroll around, I can’t get it or any of my nodes back. I get into this state by starting with an empty diagram, adding one node at the top, adding a second node at the bottom, and then dragging the second node further south so a scroll bar appears.
I noticed that the only sample which uses the Overview control is one with a static diagram. How can I get my Overview to behave with an editable diagram?
Here’s a few code snippets:
Diagram control template which places an Overview control in the lower right corner without obscuring the scroll bars:
<ControlTemplate TargetType="go:Diagram"
x:Key="DiagramTemplate">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
CanContentScroll="True"
Grid.RowSpan="2"
Grid.ColumnSpan="2">
<i:Interaction.Behaviors>
<behaviors:ScrollBarVisibilityBehavior TargetObject="{Binding ElementName=overviewContainer}" />
</i:Interaction.Behaviors>
<go:DiagramPanel x:Name="Panel"
Stretch="{TemplateBinding Stretch}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
DiagramBounds="{Binding DiagramBounds, Mode=TwoWay}"
MinimumScale="0.2"
MaximumScale="4.0">
<i:Interaction.Behaviors>
<behaviors:ObserveDiagramBehavior Observer="{Binding ElementName=overview}" />
</i:Interaction.Behaviors>
</go:DiagramPanel>
</ScrollViewer>
<StackPanel x:Name="overviewContainer"
Grid.Row="1"
Grid.Column="1">
<Button Content="Close" />
<Border BorderThickness="1"
BorderBrush="Silver">
<go:Overview x:Name="overview" />
</Border>
</StackPanel>
</Grid>
</Border>
</ControlTemplate>
Here’s the behavior that hooks up the Overview to the Diagram via the DiagramPanel:
[code]
using System.Windows;
using System.Windows.Interactivity;
using Northwoods.GoXam;
namespace Behaviors
{
internal class ObserveDiagramBehavior : Behavior
{
public static readonly DependencyProperty ObserverProperty =
DependencyProperty.Register(“Observer”, typeof (Overview), typeof (ObserveDiagramBehavior), new PropertyMetadata(default(Overview)));
public Overview Observer
{
get { return (Overview) GetValue(ObserverProperty); }
set { SetValue(ObserverProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnLoaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= OnLoaded;
if (Observer != null)
Observer.Observed = null;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (AssociatedObject.Diagram == null || Observer == null)
return;
Observer.Observed = AssociatedObject.Diagram;
}
}
}[/code]
Here’s the ScrollBarVisibilityBehavior for completeness, but I’m fairly certain this isn’t playing into my problem:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace Behaviors
{
internal class ScrollBarVisibilityBehavior : Behavior<ScrollViewer>
{
public static readonly DependencyProperty TargetObjectProperty =
DependencyProperty.Register("TargetObject", typeof (FrameworkElement), typeof (ScrollBarVisibilityBehavior), new PropertyMetadata(default(FrameworkElement)));
public FrameworkElement TargetObject
{
get { return (FrameworkElement) GetValue(TargetObjectProperty); }
set { SetValue(TargetObjectProperty, value); }
}
private const double Epsilon = 0.0001;
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnLoaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= OnLoaded;
AssociatedObject.ScrollChanged -= OnFirstScrollChanged;
AssociatedObject.ScrollChanged -= OnScrollChanged;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
AssociatedObject.ScrollChanged += OnFirstScrollChanged;
}
private void OnFirstScrollChanged(object sender, ScrollChangedEventArgs e)
{
// The first ScrollChanged event always seems to be layout related, so skip it.
AssociatedObject.ScrollChanged -= OnFirstScrollChanged;
AssociatedObject.ScrollChanged += OnScrollChanged;
}
private void OnScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (Math.Abs(e.ViewportWidthChange) < Epsilon && Math.Abs(e.ViewportHeightChange) < Epsilon)
return;
var margin = TargetObject.Margin;
if (Math.Abs(e.ViewportWidthChange) > Epsilon)
margin.Right = e.ViewportWidthChange < 0 ? Math.Abs(e.ViewportWidthChange) : 0;
if (Math.Abs(e.ViewportHeightChange) > Epsilon)
margin.Bottom = e.ViewportHeightChange < 0 ? Math.Abs(e.ViewportHeightChange) : 0;
TargetObject.Margin = margin;
}
}
}