I am trying to use expand/collapse feature for nodes as shown below:
<go:BooleanStringConverter x:Key=“theButtonConverter” TrueString="-" FalseString="+" />
<Style x:Key=“diagramStyle” TargetType=“go:Diagram”>
<Setter Property=“Padding” Value=“10”/>
<Setter Property=“Grid.Column” Value=“1”/>
<Setter Property=“Grid.Row” Value=“0”/>
<Setter Property=“Background” Value=“White”/>
<Setter Property=“VerticalContentAlignment” Value=“Top”/>
<Setter Property=“HorizontalContentAlignment” Value=“Center”/>
<Setter Property=“VerticalAlignment” Value=“Top”/>
<Setter Property=“HorizontalAlignment” Value=“Center”/>
<Setter Property=“AllowScroll” Value=“False”/>
<Setter Property=“Grid.Column” Value=“1”/>
</Style>
<Style TargetType=“TextBlock”>
<Setter Property=“Foreground” Value=“Black”/>
<Setter Property=“FontSize” Value=“12”/>
<Setter Property=“Margin” Value=“10, 10, 5,0”/>
</Style>
<Style x:Key=“TextBlockStyle” TargetType=“TextBlock”>
<Setter Property=“FontSize” Value=“13”/>
</Style>
<Style x:Key=“ButtonStyle” TargetType=“Button”>
<Setter Property=“Background” Value=“White”/>
</Style>
 
 
 
<DataTemplate x:Key=“NodeTemplate”>
<go:NodePanel go:Part.SelectionAdorned=“True” go:Node.LocationSpot=“Center” go:Node.ToSpot=“MiddleTop”>
<Button cmd:Click.Command="{Binding DataContext.GoToDeviceCommand, ElementName=netview}"
cmd:Click.CommandParameter="{Binding Path=Data.Key}">
<StackPanel>
<Image Source="{Binding Path=Data.Picture, Converter={StaticResource textImageSourceConverter}}"
Width=“20” Height=“20” />
<TextBlock Text="{Binding Path=Data.FriendlyName}" FontSize=“13” Padding=“3,0,3,0”/>
<Button Click=“CollapseExpandButton_Click” x:Name=“myCollapseExpandButton”
Content="{Binding Path=Node.IsExpandedTree,
Converter={StaticResource theButtonConverter}}" Width=“20” Margin=“0 0 5 0”
Visibility="{Binding Path=Data.NumberOfChildren, Converter={StaticResource hasChildrenVisibilityConverter}}"/>
</StackPanel>
</Button>
</go:NodePanel>
</DataTemplate>
<DataTemplate x:Key=“LinkTemplate”>
<go:LinkPanel go:Part.SelectionElementName=“Path” go:Part.SelectionAdorned=“True”>
<go:LinkShape x:Name=“Path” go:LinkPanel.IsLinkShape=“True” Stroke=“Black” StrokeThickness=“1”/>
<go:Link.Route>
<go:Route Routing=“AvoidsNodes” Adjusting=“Scale”/>
</go:Link.Route>
</go:LinkPanel>
</DataTemplate>
<go:DataTemplateDictionary x:Key=“NodeTemplates” />
 
</FrameworkElement.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=“0” />
<RowDefinition Height="" />
<RowDefinition Height=“Auto”/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=“220”/>
<ColumnDefinition Width=""/>
<ColumnDefinition Width=“Auto”/>
</Grid.ColumnDefinitions>
 
 
<ListBox x:Name=“deviceListBox” Grid.RowSpan=“2” ItemsSource="{Binding Devices}"
HorizontalAlignment=“Stretch” HorizontalContentAlignment=“Stretch” VerticalAlignment=“Stretch” VerticalContentAlignment=“Stretch”
Margin=“5,45,15,5”>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment=“Stretch” Width=“210”>
<Button Cursor=“Hand” cmd:Click.Command="{Binding DataContext.GoToDeviceCommand, ElementName=deviceListBox}"
cmd:Click.CommandParameter="{Binding Key}" HorizontalAlignment=“Stretch” HorizontalContentAlignment=“Stretch”
VerticalContentAlignment=“Center” Background=“Transparent”>
<TextBlock TextWrapping=“Wrap” Text="{Binding FriendlyName}" HorizontalAlignment=“Stretch” Style="{StaticResource TextBlockStyle}" Margin=“5,0,0,0” />
</Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
 
 
<go:Diagram x:Name=“myWholeView” Grid.Row=“0”
SelectionChanged=“DiagramSelectionChanged”
IsReadOnly=“True”
Stretch=“UniformToFill”
HorizontalContentAlignment=“Center”
VerticalContentAlignment=“Center”
NodeTemplate="{StaticResource NodeTemplate}"
LinkTemplate="{StaticResource LinkTemplate}"
MaximumSelectionCount=“1”>
<go:Diagram.Layout>
<golayout:LayeredDigraphLayout Direction=“90” SetsPortSpots=“True” LayerSpacing=“25” />
</go:Diagram.Layout>
<!–<go:Node Id=“Highlight”>
<Ellipse Width=“1” Height=“1”
go:Part.LayerName=“Background”
go:Part.InDiagramBounds=“False”
go:Part.Selectable=“False”
go:Node.LocationSpot=“Center”>
<Shape.Fill>
</Shape.Fill>
</go:Node>–>
</go:Diagram>
<go:Diagram x:Name=“myLocalView” Grid.Row=“1” Grid.Column=“1”
NodeTemplate="{StaticResource NodeTemplate}"
LinkTemplate="{StaticResource LinkTemplate}" >
<go:Diagram.Layout >
<golayout:LayeredDigraphLayout Direction=“90” SetsPortSpots=“True” LayerSpacing=“15” />
</go:Diagram.Layout>
</go:Diagram>
</Grid>
</UserControl>
GraphLinksModel = new NetworkTopologyService().GetDevices();
}
 
 
#region GoToDeviceCommand
///
/// Command is used to select a specific device
///
public DelegateCommand<string> GoToDeviceCommand { get; private set; }
#endregion
#region GoToDevice
///
/// This method is used to select a device by the GotToDeviceCommand
///
///
public void GoToDevice(string key)
{
SetCurrentSelectedDevice(key);
}
#endregion
///
/// Find the device by key and set the ui elements values
///
///
private void SetCurrentSelectedDevice(string key)
{
Debug.Assert(!String.IsNullOrEmpty(key), “key is null or empty.”);
CurrentDevice = Devices.Where(p => p.Key == key).FirstOrDefault();
if (CurrentDevice == null) return;
FocusOn(CurrentDevice);
}
 
#region CurrentDevice
///
/// Current selected device
///
private Device _currentDevice;
public Device CurrentDevice
{
get
{
return _currentDevice;
}
set
{
if (_currentDevice == value)
return;
_currentDevice = value;
RaisePropertyChanged(() => CurrentDevice);
}
}
#endregion
#region GraphLinksModel
///
/// This property represents source of the data for the diagram
///
private GraphLinksModel<Device, String, String, LinkData> _graphLinksModel;
public GraphLinksModel<Device, String, String, LinkData> GraphLinksModel
{
get
{
return _graphLinksModel;
}
set
{
if (_graphLinksModel == value)
return;
_graphLinksModel = value;
Devices = (List<Device>)_graphLinksModel.NodesSource;
SetWholeAndLocalViews();
RaisePropertyChanged(() => GraphLinksModel);
}
}
#endregion
#region SetWholeAndLocalViews
///
/// Initialize WholeModel, LocalModel and set data for diagrams
///
private void SetWholeAndLocalViews()
{
WholeModel = InitializeGraphLinksModel();
LocalModel = InitializeGraphLinksModel();
WholeModel = GraphLinksModel;
_view.myWholeView.Model = WholeModel;
_view.myLocalView.Model = LocalModel;
LocalModel.Modifiable = true;
_view.myWholeView.InitialLayoutCompleted += WholeViewInitialLayoutCompleted;
}
#endregion
#region WholeViewInitialLayoutCompleted
///
/// Initialize wholeview diagram
///
///
///
private void WholeViewInitialLayoutCompleted(object s, DiagramEventArgs e)
{
_view.myWholeView.InitialLayoutCompleted -= WholeViewInitialLayoutCompleted;
Node node = _view.myWholeView.Nodes.ElementAtOrDefault(1);
if (node != null)
node.IsSelected = true;
}
#endregion
#region Devices
///
/// Holds the data for the devices
///
private List<Device> _devices;
public List<Device> Devices
{
get
{
return _devices;
}
set
{
if (_devices == value)
return;
_devices = value;
RaisePropertyChanged(() => Devices);
}
}
#endregion
#region WholeModel and LocalModel
GraphLinksModel<Device, String, String, LinkData> WholeModel { get; set; }
GraphLinksModel<Device, String, String, LinkData> LocalModel { get; set; }
#endregion
#region InitializeGraphLinksModel
///
/// Initializes GraphLinksModel
///
///
private static GraphLinksModel<Device, String, String, LinkData> InitializeGraphLinksModel()
{
var model = new GraphLinksModel<Device, String, String, LinkData>
{
MemberNodesPath = String.Empty,
GroupNodePath = String.Empty
};
return model;
}
#endregion
///
/// Make sure a given node data is in the LocalModel along with all of the nodes and links
/// connected to it up to some number of links in distance
///
///
public void FocusOn(Device device)
{
Contract.Assert(device != null, “data is null.”);
CurrentDevice = device;
_view.deviceListBox.SelectedItem = CurrentDevice;
// Make sure it’s visible and selected in myWholeView
Node overviewnode = _view.myWholeView.PartManager.FindNodeForData(CurrentDevice, _view.myWholeView.Model);
if (overviewnode != null)
{
_view.myWholeView.Panel.MakeVisible(overviewnode, Rect.Empty);
_view.myWholeView.Select(overviewnode);
var highlight = _view.myWholeView.PartsModel.FindNodeByKey(“Highlight”);
if (highlight != null) highlight.Location = overviewnode.Location;
}
// find all connected node data and link data, and make sure there are Parts for them
LocalModel.StartTransaction(“add local graph”);
var wanted = new HashSet<Device>();
CollectLocals(CurrentDevice, null, 2, wanted);
// and remove all node and link data that are not connected to the focussed node data
foreach (var existing in LocalModel.NodesSource.OfType<Device>().ToList())
{
if (!wanted.Contains(existing)) LocalModel.RemoveNode(existing);
}
LocalModel.CommitTransaction(“add local graph”);//Do it in transaction
// center and select that Node
_view.myLocalView.Dispatcher.BeginInvoke(() =>
{
var localnode = _view.myLocalView.PartManager.FindNodeForData(CurrentDevice, _view.myLocalView.Model);
_view.myLocalView.Panel.CenterPart(localnode);
_view.myLocalView.Select(localnode);
});
}
#endregion
///
/// this collects connected node data up to LEVEL levels away, and adds the node link data to the model
///
///
///
///
///
private void CollectLocals(Device data, LinkData linkdata, int level, HashSet<Device> wanted)
{
if (data == null) return;
// stop recursing beyond the number of levels
if (level < 0) return;
// always add the link data (but it might be null, which is OK)
LocalModel.AddLink(linkdata);
// stop if we’ve already seen the node
if (wanted.Contains(data)) return;
// otherwise add it to our collection
wanted.Add(data);
LocalModel.AddNode(data);
// recurse through all connected nodes
foreach (var link in WholeModel.GetLinksForNode(data))
{
CollectLocals(WholeModel.GetFromNodeForLink(link), link, level - 1, wanted);
CollectLocals(WholeModel.GetToNodeForLink(link), link, level - 1, wanted);
}
return numberOfChildren > 1 ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}