diff --git a/Control/AthViews/AthViews/ViewHelper.h b/Control/AthViews/AthViews/ViewHelper.h
index 5594c244396124deac04a66bd34b6dd283f9e74c..432d14f26122ab344b7f6de2d84582001546c058 100644
--- a/Control/AthViews/AthViews/ViewHelper.h
+++ b/Control/AthViews/AthViews/ViewHelper.h
@@ -225,8 +225,9 @@ namespace ViewHelper
         }
 
         //Declare remapping
+        auto proxy = inputView->proxy( queryHandle.clid(), queryHandle.key() ); //shouldn't need to test validity since queryHandle already used
         m_sg->remap( ClassID_traits< DataVector< T > >::ID(),
-                     inputView->viewKey (queryHandle.name()),
+                     proxy->name(),
                      queryHandle.name(),
                      offset );
         offset += queryHandle->size();
@@ -277,7 +278,9 @@ namespace ViewHelper
   template<typename T>
   ElementLink<T> makeLink( const SG::View* view, const SG::ReadHandle<T>& handle, size_t index )
   {
-    return ElementLink<T>( view->viewKey (handle.key()), index );
+    auto proxy = view->proxy( handle.clid(), handle.key() );
+    if ( proxy == nullptr ) throw std::runtime_error( "Attempting to make element link with invalid key " + handle.key() );
+    return ElementLink<T>( proxy->name(), index );
   }
 
 } // EOF namspace ViewHelper
diff --git a/Control/AthViews/share/ViewLinking_test.ref b/Control/AthViews/share/ViewLinking_test.ref
index d394bd76b53a898c7e92a33f8e18b3aa8322917b..5629645288f9928017370885c467c711052f2fd9 100644
--- a/Control/AthViews/share/ViewLinking_test.ref
+++ b/Control/AthViews/share/ViewLinking_test.ref
@@ -13,7 +13,8 @@ ApplicationMgr Ready
 ClassIDSvc           INFO  getRegistryEntries: read 811 CLIDRegistry entries for module ALL
 ViewLinking_test     INFO SG pointer: 0xdab760
 ClassIDSvc           INFO  getRegistryEntries: read 400 CLIDRegistry entries for module ALL
-ViewLinking_test     INFO Views that are not linked behave correctly 
-ViewLinking_test     INFO Views that are linked behave correctly 
-ViewLinking_test     INFO Hiding works as expected 
-ViewLinking_test     INFO Fall through works as expected 
+ViewLinking_test     INFO Views that are not linked behave correctly
+ViewLinking_test     INFO Views that are linked behave correctly
+ViewLinking_test     INFO Hiding works as expected
+ViewLinking_test     INFO Fall through works as expected
+ViewLinking_test     INFO Fall through works with links as expected
diff --git a/Control/AthViews/test/ViewLinking_test.cxx b/Control/AthViews/test/ViewLinking_test.cxx
index eee8ae53b1686fe59ec69c33c35963889c63e005..dff7925a4ccdd4eaa295c7a83ba6e2d2a55a2caa 100644
--- a/Control/AthViews/test/ViewLinking_test.cxx
+++ b/Control/AthViews/test/ViewLinking_test.cxx
@@ -13,20 +13,23 @@
 #include "TestTools/expect.h"
 #include "TestTools/expect_exception.h"
 #include "AthViews/View.h"
+#include "AthViews/ViewHelper.h"
 
 struct TestClass {
   int value = 0;
 };
+CLASS_DEF( TestClass, 16530831, 1 )
+
+typedef std::vector<TestClass*> TestContainer;
+CLASS_DEF( TestContainer, 16530833, 1 )
 
-CLASS_DEF( TestClass , 16530831 , 1 )
 using namespace SG;
 void testDataInView( StoreGateSvc* /*sg*/ , MsgStream& log ) {
-  auto parentView = new View( "ParentView", -1 );
 
+  // Make parent view
+  auto parentView = new View( "ParentView", -1 );
   auto t1 = std::make_unique<TestClass>();
   t1->value = 1;
-  //  auto status1 = parentView->recordObject( t1, "test1" );
-    
   {
     SG::WriteHandle<TestClass> wh( "test1" );
     wh.setProxyDict( parentView ).ignore();
@@ -34,78 +37,75 @@ void testDataInView( StoreGateSvc* /*sg*/ , MsgStream& log ) {
     VALUE( status.isSuccess() ) EXPECTED( true );
   }
 
+  // Make child view
   auto childView = new View( "ChildView", -1 );
-
   auto t2 = std::make_unique<TestClass>();
   t2->value = 2;
   {
     SG::WriteHandle<TestClass> wh( "test2" );
     wh.setProxyDict( childView ).ignore();
     auto status = wh.record( std::move( t2 ) );
-    VALUE( status.isSuccess() ) EXPECTED( true ); 
+    VALUE( status.isSuccess() ) EXPECTED( true );
   }
-  //  auto status2 = childView->recordObject( t2, "test1" );
-  // all prepared, will start testing if querries respond correctly
+
+  // All prepared, will start testing if queries respond correctly
   {
-    // rtivial test, we ask for a wrong object
+    // Ask for an object that doesn't exist
     SG::ReadHandle<TestClass> rh( "test" );
     rh.setProxyDict( childView ).ignore();
     VALUE( rh.isValid() ) EXPECTED( false );
   }
-
-
-
   {
+    // Ask for object in the child view
     SG::ReadHandle<TestClass> rh( "test2" );
     rh.setProxyDict( childView ).ignore();
     VALUE( rh.isValid() ) EXPECTED( true );
     VALUE( rh->value ) EXPECTED( 2 );
   }
-
   {
+    // Ask child view for object that only exists in the parent
     SG::ReadHandle<TestClass> rh( "test1" );
     rh.setProxyDict( childView ).ignore();
     VALUE( rh.isValid() ) EXPECTED( false );
   }
-  log << MSG::INFO << "Views that are not linked behave correctly " << endmsg;
-  // link them and see if data object is accessible
-  childView->linkParent( parentView );
+  log << MSG::INFO << "Views that are not linked behave correctly" << endmsg;
 
+  // Link views and see if data object is accessible
+  childView->linkParent( parentView );
   {
+    // Is the original object still there?
     SG::ReadHandle<TestClass> rh( "test2" );
     rh.setProxyDict( childView ).ignore();
     VALUE( rh.isValid() ) EXPECTED( true );
     VALUE( rh->value ) EXPECTED( 2 );
   }
   {
+    // Is the object from the parent now also visible?
     SG::ReadHandle<TestClass> rh( "test1" );
     rh.setProxyDict( childView ).ignore();
     VALUE( rh.isValid() ) EXPECTED( true );
     VALUE( rh->value ) EXPECTED( 1 );
   }
-  log << MSG::INFO << "Views that are linked behave correctly " << endmsg;
+  log << MSG::INFO << "Views that are linked behave correctly" << endmsg;
 
-  // hide object from parent by adding one in the Child
+  // Hide object from parent by adding one with same name to the Child
   auto t3 = std::make_unique<TestClass>();
   t3->value = 3;
-
   {
+    // Can it be recorded? (should be allowed)
     SG::WriteHandle<TestClass> wh( "test1" );
     wh.setProxyDict( childView ).ignore();
     auto status = wh.record( std::move( t3 ) );
     VALUE( status.isSuccess() ) EXPECTED( true );
   }
-
   {
+    // Do we now see the child object in preference to the parent?
     SG::ReadHandle<TestClass> rh( "test1" );
     rh.setProxyDict( childView ).ignore();
     VALUE( rh.isValid() ) EXPECTED( true );
     VALUE( rh->value ) EXPECTED ( 3 );
   }
-
-  log << MSG::INFO << "Hiding works as expected " << endmsg;
-
-
+  log << MSG::INFO << "Hiding works as expected" << endmsg;
 }
 
 void testFallThrough( StoreGateSvc* sg , MsgStream& log) {
@@ -113,8 +113,8 @@ void testFallThrough( StoreGateSvc* sg , MsgStream& log) {
   SG::WriteHandle<TestClass> wh( "inStore" );
   wh.setProxyDict( sg ).ignore();
   auto status = wh.record( std::move( t ) );
-  VALUE( status.isSuccess() ) EXPECTED( true ); 
-    
+  VALUE( status.isSuccess() ) EXPECTED( true );
+
   // the whole trick is that the read handle is pointed to the view,
   // but should read from the main store if the fall though
   // is enabled
@@ -130,21 +130,86 @@ void testFallThrough( StoreGateSvc* sg , MsgStream& log) {
     rh.setProxyDict( transparentView ).ignore();
     VALUE( rh.isValid() ) EXPECTED( true );
   }
-  log << MSG::INFO << "Fall through works as expected " << endmsg;
+  log << MSG::INFO << "Fall through works as expected" << endmsg;
 }
 
+void testFallThroughLinks( StoreGateSvc* sg , MsgStream& log ) {
 
+  // Have to make a container to test element links
+  auto t = std::make_unique<TestContainer>();
+  t->push_back( new TestClass() );
+  t->back()->value = 5;
+  t->push_back( new TestClass() );
+  t->back()->value = 4;
+
+  // Store the container in the event-level store
+  SG::WriteHandle<TestContainer> wh( "inStore" );
+  wh.setProxyDict( sg ).ignore();
+  auto status = wh.record( std::move( t ) );
+  VALUE( status.isSuccess() ) EXPECTED( true );
+
+  // Make another container for testing parent/child links
+  auto t2 = std::make_unique<TestContainer>();
+  t2->push_back( new TestClass() );
+  t2->back()->value = 3;
+  t2->push_back( new TestClass() );
+  t2->back()->value = 2;
+
+  // Make a parent view and store the container
+  auto parentView = new View( "parentView", -1 );
+  SG::WriteHandle<TestContainer> wh2( "inParent" );
+  wh2.setProxyDict( parentView ).ignore();
+  status = wh2.record( std::move( t2 ) );
+  VALUE( status.isSuccess() ) EXPECTED( true );
+
+  // Just test a straightforward element link to the parent
+  {
+    SG::ReadHandle<TestContainer> rh( "inParent" );
+    auto link = ViewHelper::makeLink( parentView, rh, 0 );
+    VALUE( link.isValid() ) EXPECTED( true );
+    VALUE( ( *link )->value ) EXPECTED( 3 );
+    VALUE( link.proxy()->name() == "_parentView_inParent" ) EXPECTED( true );
+  }
+
+  // Element links need to point to the right object
+  // even if it's not in the current view
+  {
+    // Child to parent
+    auto childView = new View( "childView", -1 );
+    childView->linkParent( parentView );
+    SG::ReadHandle<TestContainer> rh( "inParent" );
+    auto link = ViewHelper::makeLink( childView, rh, 1 );
+    VALUE( link.isValid() ) EXPECTED( true );
+    VALUE( ( *link )->value ) EXPECTED( 2 );
+    VALUE( link.proxy()->name() == "_parentView_inParent" ) EXPECTED( true );
+  }
+  {
+    // Parent to store
+    SG::ReadHandle<TestContainer> rh( "inStore" );
+    auto link = ViewHelper::makeLink( parentView, rh, 0 );
+    VALUE( link.isValid() ) EXPECTED( true );
+    VALUE( ( *link )->value ) EXPECTED( 5 );
+    VALUE( link.proxy()->name() == "inStore" ) EXPECTED( true );
+  }
+  {
+    // Child to store
+    auto childView = new View( "childView", -1 );
+    childView->linkParent( parentView );
+    SG::ReadHandle<TestContainer> rh( "inStore" );
+    auto link = ViewHelper::makeLink( childView, rh, 1 );
+    VALUE( link.isValid() ) EXPECTED( true );
+    VALUE( ( *link )->value ) EXPECTED( 4 );
+    VALUE( link.proxy()->name() == "inStore" ) EXPECTED( true );
+  }
+  log << MSG::INFO << "Fall through works with links as expected" << endmsg;
+}
 
 int main() {
   using namespace std;
 
   MsgStream log(Athena::getMessageSvc(), "ViewLinking_test");
 
-  //  MsgStream* msglog = &log;
-
-
   ISvcLocator* pSvcLoc;
-  //if (!Athena_test::initGaudi("test.txt",  pSvcLoc)) {
   if (!Athena_test::initGaudi("",  pSvcLoc)) {
     log << MSG::ERROR << "Can not intit Gaudi" << endmsg;
     return -1;
@@ -162,6 +227,7 @@ int main() {
 
   testDataInView( pStore, log );
   testFallThrough( pStore, log );
-  
+  testFallThroughLinks( pStore, log );
+
   return 0;
 }