well the whole thing could be done with data binding so as you update the location of a bulb it auto updates the UI, stay with me here the code example is a bit long..
the result of this demo is just some circles with lines joining them but you could template this up however you want.

The xaml window, this declares an items control that will display the bulbs (and the lines joining them)
<Window x:Class="points.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:points"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<ItemsControl ItemsSource="{Binding Bulbs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas HorizontalAlignment="Left" VerticalAlignment="Top">
<Ellipse Fill="Blue" Width="10" Height="10">
<Ellipse.RenderTransform>
<TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
</Ellipse.RenderTransform>
</Ellipse>
<Line X1="{Binding X}" Y1="{Binding Y}" X2="{Binding NextBulb.X}" Y2="{Binding NextBulb.Y}" Stroke="Red">
<Line.RenderTransform>
<TranslateTransform X="5" Y="5"/>
</Line.RenderTransform>
</Line>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Window>
and this is the cs, I've created a bulb structure that holds the X and Y location of a bulb and a reference to the next bulb in the chain, I've placed all bulbs in to a line and then just moved the Y location of element 5 a bit lower to show it updating.
using System.Collections.ObjectModel;
using System.Windows;
namespace points
{
public class Bulb : DependencyObject
{
public double X
{
get { return (double)GetValue(XProperty); }
set { SetValue(XProperty, value); }
}
public static readonly DependencyProperty XProperty =
DependencyProperty.Register("X", typeof(double), typeof(Bulb), new PropertyMetadata(0d));
public double Y
{
get { return (double)GetValue(YProperty); }
set { SetValue(YProperty, value); }
}
public static readonly DependencyProperty YProperty =
DependencyProperty.Register("Y", typeof(double), typeof(Bulb), new PropertyMetadata(0d));
public Bulb NextBulb
{
get { return (Bulb)GetValue(NextBulbProperty); }
set { SetValue(NextBulbProperty, value); }
}
public static readonly DependencyProperty NextBulbProperty =
DependencyProperty.Register("NextBulb", typeof(Bulb), typeof(Bulb), new PropertyMetadata(null));
}
public partial class MainWindow : Window
{
public ObservableCollection<Bulb> Bulbs
{
get { return (ObservableCollection<Bulb>)GetValue(BulbsProperty); }
set { SetValue(BulbsProperty, value); }
}
public static readonly DependencyProperty BulbsProperty =
DependencyProperty.Register("Bulbs", typeof(ObservableCollection<Bulb>), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
Bulbs = new ObservableCollection<Bulb>();
InitializeComponent();
for (int i = 0; i < 10; i++)
{
double x = i * 50;
double y = 25;
Bulbs.Add(new Bulb()
{
X = x,
Y = y,
NextBulb = i > 0 ? Bulbs[i - 1] : null,
});
}
Bulbs[5].Y = 50;
}
}
}
The outcome of this is that altering the Bulbs structure in any way will update the bulb display on the UI without having to clear and recreate your collection every time, you can even run animations on the properties for some pretty cool effects.