diff --git a/Modules/ROI/include/mitkROI.h b/Modules/ROI/include/mitkROI.h
index f8295e43b4..25fb2ad7bc 100644
--- a/Modules/ROI/include/mitkROI.h
+++ b/Modules/ROI/include/mitkROI.h
@@ -1,197 +1,202 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #ifndef mitkROI_h
 #define mitkROI_h
 
 #include <mitkBaseData.h>
 #include <MitkROIExports.h>
 
 namespace mitk
 {
   /** \brief A collection of region of interests (ROIs).
     *
     * \note This class is considered experimental and subject to substational change. We mean it.
     *
     * ROIs, essentially defined by the minimum and maximum index coordinates of an axis-aligned box, are
     * represented by the nested ROI::Element class. These index coordinates are relative to a common
     * TimeGeometry.
     *
     * All ROIs are required to have a unique ID by which they can be accessed.
     *
     * ROIs can optionally have properties (PropertyList), also called default properties. In case of
     * time-resolved ROIs, each time step can optionally have properties, too. These properties have
     * precedence over the default properties. In other words, the default properties may contain
     * fallback properties which are queried when a property is not defined at a certain time step.
     * This allows for an opt-in dynamic appearance of ROIs over time, for example by changing
     * color or opacity.
     *
     * ROIs are rendered both in 3-d and 2-d views as cubes, resp. cutting slices of these cubes.
     * They support the following ROI::Element properties:
     *
     *   - \c color (ColorProperty): Color of the cube
     *   - \c opacity (FloatProperty): Opacity of the cube
     *   - \c lineWidth (FloatProperty): %Line width of the cube edges
     *
     * ROIs display a customizable caption at their bottom-left corner. It is defined by the base data
     * property \c caption (StringProperty). By default it is set to <tt>"{name} ({ID})"</tt>. Braces
     * are used to define placeholders which are replaced by their corresponding ROI::Element properties.
     * <tt>{ID}</tt> is a special placeholder which will be replaced by the ID of the ROI::Element instead.
     * The caption is allowed to include line breaks. Rendering of captions can be customized through the
     * following data node properties:
     *
     *   - \c font.size (IntProperty) Font size in points
     *   - \c font.bold (BoolProperty) Bold font style
     *   - \c font.italic (BoolProperty) Italic font style
     *
     * See \ref MITKROIPage for details on the JSON-based MITK %ROI file format.
     */
   class MITKROI_EXPORT ROI : public BaseData
   {
   public:
     /** \brief Encapsulates a single (possibly time-resolved) %ROI.
       *
       * \sa ROI
       */
     class MITKROI_EXPORT Element : public IPropertyOwner
     {
     public:
       using PointsType = std::map<TimeStepType, Point3D>;
       using PropertyListsType = std::map<TimeStepType, PropertyList::Pointer>;
 
       Element();
       explicit Element(unsigned int id);
       ~Element() = default;
 
       /** \brief Get a const property.
         *
         * \note A time step can be specified as context. Use \c std::to_string() to convert a time step to a context name.
         * An empty context name addresses the default properties.
         */
       BaseProperty::ConstPointer GetConstProperty(const std::string& propertyKey, const std::string& contextName = "", bool fallBackOnDefaultContext = true) const override;
+      BaseProperty::ConstPointer GetConstProperty(const std::string& propertyKey, TimeStepType t, bool fallBackOnDefaultContext = true) const;
 
       /** \brief Get all property keys.
         *
         * \note A time step can be specified as context. Use \c std::to_string() to convert a time step to a context name.
         * An empty context name addresses the default properties.
         */
       std::vector<std::string> GetPropertyKeys(const std::string& contextName = "", bool includeDefaultContext = false) const override;
+      std::vector<std::string> GetPropertyKeys(TimeStepType t, bool includeDefaultContext = false) const;
 
       /** \brief Get all property context names (stringified time steps).
         */
       std::vector<std::string> GetPropertyContextNames() const override;
 
       /** \brief Get a property.
         *
         * \note A time step can be specified as context. Use \c std::to_string() to convert a time step to a context name.
         * An empty context name addresses the default properties.
         */
       BaseProperty* GetNonConstProperty(const std::string& propertyKey, const std::string& contextName = "", bool fallBackOnDefaultContext = true) override;
+      BaseProperty* GetNonConstProperty(const std::string& propertyKey, TimeStepType t, bool fallBackOnDefaultContext = true);
 
       /** \brief Set a property.
         *
         * \note A time step can be specified as context. Use \c std::to_string() to convert a time step to a context name.
         * An empty context name addresses the default properties.
         */
       void SetProperty(const std::string& propertyKey, BaseProperty* property, const std::string& contextName = "", bool fallBackOnDefaultContext = false) override;
+      void SetProperty(const std::string& propertyKey, BaseProperty* property, TimeStepType t, bool fallBackOnDefaultContext = false);
 
       /** \brief Remove a property.
         *
         * \note A time step can be specified as context. Use \c std::to_string() to convert a time step to a context name.
         * An empty context name addresses the default properties.
         */
       void RemoveProperty(const std::string& propertyKey, const std::string& contextName = "", bool fallBackOnDefaultContext = false) override;
+      void RemoveProperty(const std::string& propertyKey, TimeStepType t, bool fallBackOnDefaultContext = false);
 
       unsigned int GetID() const;
       void SetID(unsigned int id);
 
       /** \brief Check if the %ROI is defined for a certain time step.
         */
       bool HasTimeStep(TimeStepType t) const;
 
       /** \brief Check if the %ROI can be considered time-resolved.
         */
       bool HasTimeSteps() const;
 
       /** \brief Get all valid time steps that have a minimum point and a maximum point.
         */
       std::vector<TimeStepType> GetTimeSteps() const;
 
       Point3D GetMin(TimeStepType t = 0) const;
       void SetMin(const Point3D& min, TimeStepType t = 0);
 
       Point3D GetMax(TimeStepType t = 0) const;
       void SetMax(const Point3D& max, TimeStepType t = 0);
 
       PropertyList* GetDefaultProperties() const;
       void SetDefaultProperties(PropertyList* properties);
 
       /** \brief Get properties for a certain time step or \c nullptr if absent.
         */
       PropertyList* GetProperties(TimeStepType t = 0) const;
 
       void SetProperties(PropertyList* properties, TimeStepType t = 0);
 
     private:
       unsigned int m_ID;
       PointsType m_Min;
       PointsType m_Max;
       PropertyList::Pointer m_DefaultProperties;
       PropertyListsType m_Properties;
     };
 
     mitkClassMacro(ROI, BaseData)
     itkFactorylessNewMacro(Self)
     itkCloneMacro(Self)
 
     using ElementsType = std::map<unsigned int, Element>;
     using Iterator = ElementsType::iterator;
     using ConstIterator = ElementsType::const_iterator;
 
     size_t GetNumberOfElements() const;
 
     /** \brief Add a ROI::Element to the collection.
       *
       * \note The ID of the ROI::Element must be set to a unique number in advance.
       */
     void AddElement(const Element& element);
 
     const Element& GetElement(unsigned int id) const;
     Element& GetElement(unsigned int id);
 
     ConstIterator begin() const;
     ConstIterator end() const;
 
     Iterator begin();
     Iterator end();
 
     void SetRequestedRegionToLargestPossibleRegion() override;
     bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
     bool VerifyRequestedRegion() override;
     void SetRequestedRegion(const itk::DataObject* data) override;
 
   protected:
     mitkCloneMacro(Self)
 
     ROI();
     ROI(const Self& other);
     ~ROI() override;
 
   private:
     ElementsType m_Elements;
   };
 
   MITKROI_EXPORT void to_json(nlohmann::json& j, const ROI::Element& roi);
   MITKROI_EXPORT void from_json(const nlohmann::json& j, ROI::Element& roi);
 }
 
 #endif
diff --git a/Modules/ROI/src/mitkROI.cpp b/Modules/ROI/src/mitkROI.cpp
index c9a07ead46..6f5e614b1a 100644
--- a/Modules/ROI/src/mitkROI.cpp
+++ b/Modules/ROI/src/mitkROI.cpp
@@ -1,378 +1,399 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include <mitkROI.h>
 
 void mitk::to_json(nlohmann::json& j, const ROI::Element& roi)
 {
   j["ID"] = roi.GetID();
 
   if (roi.HasTimeSteps())
   {
     auto timeSteps = roi.GetTimeSteps();
 
     for (const auto t : timeSteps)
     {
       nlohmann::json jTimeStep = {
         { "t", t },
         { "Min", roi.GetMin(t) },
         { "Max", roi.GetMax(t) }
       };
 
       if (auto* properties = roi.GetProperties(t); properties != nullptr && !properties->IsEmpty())
         properties->ToJSON(jTimeStep["Properties"]);
 
       j["TimeSteps"].push_back(jTimeStep);
     }
   }
   else
   {
     j["Min"] = roi.GetMin();
     j["Max"] = roi.GetMax();
   }
 
   if (auto* properties = roi.GetDefaultProperties(); properties != nullptr && !properties->IsEmpty())
     properties->ToJSON(j["Properties"]);
 }
 
 void mitk::from_json(const nlohmann::json& j, ROI::Element& roi)
 {
   auto id = j["ID"].get<unsigned int>();
   roi.SetID(id);
 
   if (j.contains("TimeSteps"))
   {
     for (const auto& jTimeStep : j["TimeSteps"])
     {
       auto t = jTimeStep["t"].get<TimeStepType>();
 
       roi.SetMin(jTimeStep["Min"].get<Point3D>(), t);
       roi.SetMax(jTimeStep["Max"].get<Point3D>(), t);
 
       if (jTimeStep.contains("Properties"))
       {
         auto properties = mitk::PropertyList::New();
         properties->FromJSON(jTimeStep["Properties"]);
         roi.SetProperties(properties, t);
       }
     }
   }
   else
   {
     roi.SetMin(j["Min"].get<Point3D>());
     roi.SetMax(j["Max"].get<Point3D>());
   }
 
   if (j.contains("Properties"))
   {
     auto properties = mitk::PropertyList::New();
     properties->FromJSON(j["Properties"]);
     roi.SetDefaultProperties(properties);
   }
 }
 
 mitk::ROI::Element::Element()
   : Element(0)
 {
 }
 
 mitk::ROI::Element::Element(unsigned int id)
   : m_ID(id),
     m_DefaultProperties(PropertyList::New())
 {
 }
 
 unsigned int mitk::ROI::Element::GetID() const
 {
   return m_ID;
 }
 
 void mitk::ROI::Element::SetID(unsigned int id)
 {
   m_ID = id;
 }
 
 bool mitk::ROI::Element::HasTimeStep(TimeStepType t) const
 {
   return m_Min.count(t) != 0 && m_Max.count(t) != 0;
 }
 
 bool mitk::ROI::Element::HasTimeSteps() const
 {
   // Check for multiple time steps.
   if (m_Min.size() > 1 && m_Max.size() > 1)
     return true;
 
   // Check for single time step that is not 0.
   if (m_Min.size() >= 1 && m_Max.size() >= 1)
     return m_Min.count(0) == 0 && m_Max.count(0) == 0;
 
   // Single time step 0.
   return false;
 }
 
 std::vector<mitk::TimeStepType> mitk::ROI::Element::GetTimeSteps() const
 {
   std::vector<TimeStepType> result;
   result.reserve(m_Min.size());
 
   for (const auto& [t, min] : m_Min)
   {
     if (m_Max.count(t) != 0)
       result.push_back(t);
   }
 
   return result;
 }
 
 mitk::Point3D mitk::ROI::Element::GetMin(TimeStepType t) const
 {
   return m_Min.at(t);
 }
 
 void mitk::ROI::Element::SetMin(const Point3D& min, TimeStepType t)
 {
   m_Min[t] = min;
 }
 
 mitk::Point3D mitk::ROI::Element::GetMax(TimeStepType t) const
 {
   return m_Max.at(t);
 }
 
 void mitk::ROI::Element::SetMax(const Point3D& max, TimeStepType t)
 {
   m_Max[t] = max;
 }
 
 mitk::PropertyList* mitk::ROI::Element::GetDefaultProperties() const
 {
   return m_DefaultProperties;
 }
 
 void mitk::ROI::Element::SetDefaultProperties(PropertyList* properties)
 {
   m_DefaultProperties = properties;
 }
 
 mitk::PropertyList* mitk::ROI::Element::GetProperties(TimeStepType t) const
 {
   if (m_Properties.count(t) != 0)
     return m_Properties.at(t);
 
   return nullptr;
 }
 
 void mitk::ROI::Element::SetProperties(PropertyList* properties, TimeStepType t)
 {
   m_Properties[t] = properties;
 }
 
 mitk::BaseProperty::ConstPointer mitk::ROI::Element::GetConstProperty(const std::string& propertyKey, const std::string& contextName, bool fallBackOnDefaultContext) const
 {
-  if (!contextName.empty())
-  {
-    const TimeStepType t = std::stoul(contextName);
-    auto it = m_Properties.find(t);
+  return !contextName.empty()
+    ? this->GetConstProperty(propertyKey, std::stoul(contextName), fallBackOnDefaultContext)
+    : m_DefaultProperties->GetConstProperty(propertyKey);
+}
 
-    if (it != m_Properties.end() && it->second.IsNotNull())
-    {
-      auto property = it->second->GetConstProperty(propertyKey);
+mitk::BaseProperty::ConstPointer mitk::ROI::Element::GetConstProperty(const std::string& propertyKey, TimeStepType t, bool fallBackOnDefaultContext) const
+{
+  auto it = m_Properties.find(t);
 
-      if (property.IsNotNull())
-        return property;
-    }
+  if (it != m_Properties.end() && it->second.IsNotNull())
+  {
+    auto property = it->second->GetConstProperty(propertyKey);
 
-    if (!fallBackOnDefaultContext)
-      return nullptr;
+    if (property.IsNotNull())
+      return property;
   }
 
+  if (!fallBackOnDefaultContext)
+    return nullptr;
+
   return m_DefaultProperties->GetConstProperty(propertyKey);
 }
 
 std::vector<std::string> mitk::ROI::Element::GetPropertyKeys(const std::string& contextName, bool includeDefaultContext) const
 {
-  if (!contextName.empty())
-  {
-    const TimeStepType t = std::stoul(contextName);
-    auto it = m_Properties.find(t);
+  return !contextName.empty()
+    ? this->GetPropertyKeys(std::stoul(contextName), includeDefaultContext)
+    : m_DefaultProperties->GetPropertyKeys();
+}
 
-    std::vector<std::string> result;
+std::vector<std::string> mitk::ROI::Element::GetPropertyKeys(TimeStepType t, bool includeDefaultContext) const
+{
+  auto it = m_Properties.find(t);
 
-    if (it != m_Properties.end() && it->second.IsNotNull())
-      result = it->second->GetPropertyKeys();
+  std::vector<std::string> result;
 
-    if (includeDefaultContext)
-    {
-      auto keys = m_DefaultProperties->GetPropertyKeys();
-      auto end = result.cend();
+  if (it != m_Properties.end() && it->second.IsNotNull())
+    result = it->second->GetPropertyKeys();
 
-      std::remove_copy_if(keys.cbegin(), keys.cend(), std::back_inserter(result), [&, result, end](const std::string& key) {
-        return end != std::find(result.cbegin(), end, key);
-      });
-    }
+  if (includeDefaultContext)
+  {
+    auto keys = m_DefaultProperties->GetPropertyKeys();
+    auto end = result.cend();
 
-    return result;
+    std::remove_copy_if(keys.cbegin(), keys.cend(), std::back_inserter(result), [&, result, end](const std::string& key) {
+      return end != std::find(result.cbegin(), end, key);
+    });
   }
 
-  return m_DefaultProperties->GetPropertyKeys();
+  return result;
 }
 
 std::vector<std::string> mitk::ROI::Element::GetPropertyContextNames() const
 {
   std::vector<std::string> result;
   result.reserve(m_Properties.size());
 
   std::transform(m_Properties.cbegin(), m_Properties.cend(), std::back_inserter(result), [](const PropertyListsType::value_type& property) {
     return std::to_string(property.first);
   });
 
   return result;
 }
 
 mitk::BaseProperty* mitk::ROI::Element::GetNonConstProperty(const std::string& propertyKey, const std::string& contextName, bool fallBackOnDefaultContext)
 {
-  if (!contextName.empty())
-  {
-    const TimeStepType t = std::stoul(contextName);
-    auto it = m_Properties.find(t);
+  return !contextName.empty()
+    ? this->GetNonConstProperty(propertyKey, std::stoul(contextName), fallBackOnDefaultContext)
+    : m_DefaultProperties->GetNonConstProperty(propertyKey);
+}
 
-    if (it != m_Properties.end() && it->second.IsNotNull())
-    {
-      auto* property = it->second->GetNonConstProperty(propertyKey);
+mitk::BaseProperty* mitk::ROI::Element::GetNonConstProperty(const std::string& propertyKey, TimeStepType t, bool fallBackOnDefaultContext)
+{
+  auto it = m_Properties.find(t);
 
-      if (property != nullptr)
-        return property;
-    }
+  if (it != m_Properties.end() && it->second.IsNotNull())
+  {
+    auto* property = it->second->GetNonConstProperty(propertyKey);
 
-    if (!fallBackOnDefaultContext)
-      return nullptr;
+    if (property != nullptr)
+      return property;
   }
 
+  if (!fallBackOnDefaultContext)
+    return nullptr;
+
   return m_DefaultProperties->GetNonConstProperty(propertyKey);
 }
 
 void mitk::ROI::Element::SetProperty(const std::string& propertyKey, BaseProperty* property, const std::string& contextName, bool fallBackOnDefaultContext)
 {
   if (!contextName.empty())
   {
-    const TimeStepType t = std::stoul(contextName);
-    auto it = m_Properties.find(t);
+    this->SetProperty(propertyKey, property, std::stoul(contextName), fallBackOnDefaultContext);
+    return;
+  }
 
-    if (it != m_Properties.end() && it->second.IsNotNull())
-    {
-      it->second->SetProperty(propertyKey, property);
-      return;
-    }
+  m_DefaultProperties->SetProperty(propertyKey, property);
+}
 
-    if (!fallBackOnDefaultContext)
-      mitkThrow() << "Context \"" << contextName << "\" does not exist!";
+void mitk::ROI::Element::SetProperty(const std::string& propertyKey, BaseProperty* property, TimeStepType t, bool fallBackOnDefaultContext)
+{
+  auto it = m_Properties.find(t);
+
+  if (it != m_Properties.end() && it->second.IsNotNull())
+  {
+    it->second->SetProperty(propertyKey, property);
+    return;
   }
 
+  if (!fallBackOnDefaultContext)
+    mitkThrow() << "Time step " << t << " does not exist!";
+
   m_DefaultProperties->SetProperty(propertyKey, property);
 }
 
 void mitk::ROI::Element::RemoveProperty(const std::string& propertyKey, const std::string& contextName, bool fallBackOnDefaultContext)
 {
   if (!contextName.empty())
   {
-    const TimeStepType t = std::stoul(contextName);
-    auto it = m_Properties.find(t);
+    this->RemoveProperty(propertyKey, std::stoul(contextName), fallBackOnDefaultContext);
+    return;
+  }
 
-    if (it != m_Properties.end() && it->second.IsNotNull())
-    {
-      it->second->RemoveProperty(propertyKey);
-      return;
-    }
+  m_DefaultProperties->RemoveProperty(propertyKey);
+}
+
+void mitk::ROI::Element::RemoveProperty(const std::string& propertyKey, TimeStepType t, bool fallBackOnDefaultContext)
+{
+  auto it = m_Properties.find(t);
 
-    if (!fallBackOnDefaultContext)
-      mitkThrow() << "Context \"" << contextName << "\" does not exist!";
+  if (it != m_Properties.end() && it->second.IsNotNull())
+  {
+    it->second->RemoveProperty(propertyKey);
+    return;
   }
 
+  if (!fallBackOnDefaultContext)
+    mitkThrow() << "Time step " << t << " does not exist!";
+
   m_DefaultProperties->RemoveProperty(propertyKey);
 }
 
 mitk::ROI::ROI()
 {
 }
 
 mitk::ROI::ROI(const Self& other)
   : BaseData(other)
 {
 }
 
 mitk::ROI::~ROI()
 {
 }
 
 size_t mitk::ROI::GetNumberOfElements() const
 {
   return m_Elements.size();
 }
 
 void mitk::ROI::AddElement(const Element& element)
 {
   const auto id = element.GetID();
 
   if (m_Elements.count(id) != 0)
     mitkThrow() << "ROI already contains an element with ID " << std::to_string(id) << '.';
 
   m_Elements[id] = element;
 }
 
 const mitk::ROI::Element& mitk::ROI::GetElement(unsigned int id) const
 {
   return m_Elements.at(id);
 }
 
 mitk::ROI::Element& mitk::ROI::GetElement(unsigned int id)
 {
   return m_Elements.at(id);
 }
 
 mitk::ROI::ConstIterator mitk::ROI::begin() const
 {
   return m_Elements.begin();
 }
 
 mitk::ROI::ConstIterator mitk::ROI::end() const
 {
   return m_Elements.end();
 }
 
 mitk::ROI::Iterator mitk::ROI::begin()
 {
   return m_Elements.begin();
 }
 
 mitk::ROI::Iterator mitk::ROI::end()
 {
   return m_Elements.end();
 }
 
 void mitk::ROI::SetRequestedRegionToLargestPossibleRegion()
 {
 }
 
 bool mitk::ROI::RequestedRegionIsOutsideOfTheBufferedRegion()
 {
   return false;
 }
 
 bool mitk::ROI::VerifyRequestedRegion()
 {
   return true;
 }
 
 void mitk::ROI::SetRequestedRegion(const itk::DataObject*)
 {
 }
diff --git a/Modules/ROI/src/mitkROIMapperHelper.cpp b/Modules/ROI/src/mitkROIMapperHelper.cpp
index 685d095794..68dc54c545 100644
--- a/Modules/ROI/src/mitkROIMapperHelper.cpp
+++ b/Modules/ROI/src/mitkROIMapperHelper.cpp
@@ -1,132 +1,130 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "mitkROIMapperHelper.h"
 
 #include <vtkTextActor.h>
 #include <vtkTextProperty.h>
 
 #include <boost/algorithm/string.hpp>
 
 #include <regex>
 
-void mitk::ROIMapperHelper::ApplyIndividualProperties(const IPropertyProvider& properties, TimeStepType t, vtkActor* actor)
+void mitk::ROIMapperHelper::ApplyIndividualProperties(const ROI::Element& roi, TimeStepType t, vtkActor* actor)
 {
   auto* property = actor->GetProperty();
 
   property->SetRepresentationToWireframe();
   property->LightingOff();
 
-  const auto contextName = std::to_string(t);
-
-  if (auto colorProperty = GetConstProperty<ColorProperty>("color", properties, contextName); colorProperty != nullptr)
+  if (auto colorProperty = GetConstProperty<ColorProperty>("color", roi, t); colorProperty != nullptr)
   {
     const auto color = colorProperty->GetColor();
     property->SetColor(color[0], color[1], color[2]);
   }
 
-  if (auto opacityProperty = GetConstProperty<FloatProperty>("opacity", properties, contextName); opacityProperty != nullptr)
+  if (auto opacityProperty = GetConstProperty<FloatProperty>("opacity", roi, t); opacityProperty != nullptr)
   {
     const auto opacity = opacityProperty->GetValue();
     property->SetOpacity(property->GetOpacity() * opacity);
   }
 
-  if (auto lineWidthProperty = GetConstProperty<FloatProperty>("lineWidth", properties, contextName); lineWidthProperty != nullptr)
+  if (auto lineWidthProperty = GetConstProperty<FloatProperty>("lineWidth", roi, t); lineWidthProperty != nullptr)
   {
     const auto lineWidth = lineWidthProperty->GetValue();
     property->SetLineWidth(lineWidth);
   }
 }
 
 vtkSmartPointer<vtkCaptionActor2D> mitk::ROIMapperHelper::CreateCaptionActor(const std::string& caption, const Point3D& attachmentPoint, vtkProperty* property, const DataNode* dataNode, const BaseRenderer* renderer)
 {
   auto captionActor = vtkSmartPointer<vtkCaptionActor2D>::New();
   captionActor->SetPosition(property->GetLineWidth() * 0.5, property->GetLineWidth() * 0.5);
   captionActor->GetTextActor()->SetTextScaleModeToNone();
   captionActor->SetAttachmentPoint(attachmentPoint[0], attachmentPoint[1], attachmentPoint[2]);
   captionActor->SetCaption(caption.c_str());
   captionActor->BorderOff();
   captionActor->LeaderOff();
 
   auto* textProperty = captionActor->GetCaptionTextProperty();
   textProperty->SetColor(property->GetColor());
   textProperty->SetOpacity(property->GetOpacity());
   textProperty->ShadowOff();
 
   int fontSize = 16;
   dataNode->GetIntProperty("font.size", fontSize, renderer);
   textProperty->SetFontSize(fontSize);
 
   bool bold = false;
   dataNode->GetBoolProperty("font.bold", bold, renderer);
   textProperty->SetBold(bold);
 
   bool italic = false;
   dataNode->GetBoolProperty("font.italic", italic, renderer);
   textProperty->SetItalic(italic);
 
   return captionActor;
 }
 
 std::string mitk::ROIMapperHelper::ParseCaption(const std::string& captionTemplate, const ROI::Element& roi, TimeStepType t)
 {
   std::regex regex(R"(\{([^}]*)\})"); // Anything between curly braces (considered as placeholder).
 
   auto start = captionTemplate.cbegin();
   bool hasPlaceholders = false;
   std::string caption;
   std::smatch match;
 
   // Iterate through the caption template and substitute all
   // placeholders with corresponding data or property values.
 
   while (std::regex_search(start, captionTemplate.cend(), match, regex))
   {
     hasPlaceholders = true;
 
     caption.append(match.prefix().first, match.prefix().second);
 
     if (match[1] == "ID")
     {
       caption.append(std::to_string(roi.GetID()));
     }
     else
     {
-      auto property = roi.GetConstProperty(match[1], std::to_string(t));
+      auto property = roi.GetConstProperty(match[1], t);
 
       if (property.IsNotNull())
         caption.append(property->GetValueAsString());
     }
 
     start = match.suffix().first;
   }
 
   if (match.suffix().matched)
     caption.append(match.suffix().first, match.suffix().second);
 
   if (hasPlaceholders)
   {
     boost::trim(caption);
     return caption;
   }
 
   return captionTemplate;
 }
 
 void mitk::ROIMapperHelper::SetDefaultProperties(DataNode* node, BaseRenderer* renderer, bool override)
 {
   node->AddProperty("opacity", FloatProperty::New(1.0f), renderer, override);
   node->AddProperty("font.bold", BoolProperty::New(false), renderer, override);
   node->AddProperty("font.italic", BoolProperty::New(false), renderer, override);
   node->AddProperty("font.size", IntProperty::New(16), renderer, override);
   node->AddProperty("caption", StringProperty::New("{ID}\n{name}"), renderer, override);
 }
diff --git a/Modules/ROI/src/mitkROIMapperHelper.h b/Modules/ROI/src/mitkROIMapperHelper.h
index a529cc5b99..edab2ad05d 100644
--- a/Modules/ROI/src/mitkROIMapperHelper.h
+++ b/Modules/ROI/src/mitkROIMapperHelper.h
@@ -1,60 +1,60 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #ifndef mitkROIMapperHelper_h
 #define mitkROIMapperHelper_h
 
 #include <mitkBaseRenderer.h>
 #include <mitkROI.h>
 
 #include <vtkCaptionActor2D.h>
 #include <vtkProperty.h>
 #include <vtkSmartPointer.h>
 
 namespace mitk
 {
   namespace ROIMapperHelper
   {
     /** \brief Apply %ROI properties at a certain time step to the given actor.
       */
-    void ApplyIndividualProperties(const IPropertyProvider& properties, TimeStepType t, vtkActor* actor);
+    void ApplyIndividualProperties(const ROI::Element& roi, TimeStepType t, vtkActor* actor);
 
     /** \brief Create an actor for the %ROI caption located at a certain attachment point considering several properties. 
       */
     vtkSmartPointer<vtkCaptionActor2D> CreateCaptionActor(const std::string& caption, const Point3D& attachmentPoint, vtkProperty* property, const DataNode* dataNode, const BaseRenderer* renderer);
 
     /** \brief Substitute all placeholders in a caption with corresponding property values.
       *
       * \sa ROI
       */
     std::string ParseCaption(const std::string& captionTemplate, const ROI::Element& roi, TimeStepType t = 0);
 
     /** \brief Set common default properties for both 2-d and 3-d %ROI mappers.
       */
     void SetDefaultProperties(DataNode* node, BaseRenderer* renderer, bool override);
 
-    /** \brief Syntactic sugar for getting properties.
+    /** \brief Syntactic sugar for getting %ROI properties.
       */
     template <class T>
-    const T* GetConstProperty(const std::string& propertyKey, const mitk::IPropertyProvider& properties, const std::string& contextName = "")
+    const T* GetConstProperty(const std::string& propertyKey, const ROI::Element& roi, TimeStepType t)
     {
-      auto property = properties.GetConstProperty(propertyKey, contextName);
+      auto property = roi.GetConstProperty(propertyKey, t);
 
       if (property.IsNotNull())
         return dynamic_cast<const T*>(property.GetPointer());
 
       return nullptr;
     }
   }
 }
 
 #endif