diff --git a/common/dialogs/panel_setup_netclasses.cpp b/common/dialogs/panel_setup_netclasses.cpp
index 00bffa4585..def7f5b1a1 100644
--- a/common/dialogs/panel_setup_netclasses.cpp
+++ b/common/dialogs/panel_setup_netclasses.cpp
@@ -27,6 +27,7 @@
 
 #include <pgm_base.h>
 #include <base_units.h>
+#include <eda_draw_frame.h>
 #include <bitmaps.h>
 #include <netclass.h>
 #include <confirm.h>
@@ -69,11 +70,13 @@ std::vector<BITMAPS> g_lineStyleIcons;
 wxArrayString        g_lineStyleNames;
 
 
-PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, NETCLASSES* aNetclasses,
+PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_FRAME* aFrame,
+                                                NETCLASSES* aNetclasses,
                                                 const std::vector<wxString>& aNetNames,
                                                 bool aIsEEschema ) :
         PANEL_SETUP_NETCLASSES_BASE( aParent->GetTreebook() ),
-        m_Parent( aParent ),
+        m_frame( aFrame ),
+        m_parent( aParent ),
         m_netclasses( aNetclasses ),
         m_netNames( aNetNames ),
         m_hoveredCol( -1 )
@@ -185,6 +188,8 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, NETCLASSE
                                                    &PANEL_SETUP_NETCLASSES::OnNetclassGridMouseEvent,
                                                    this );
 
+    m_frame->Bind( UNITS_CHANGED, &PANEL_SETUP_NETCLASSES::onUnitsChanged, this );
+
     m_netclassGrid->EndBatch();
     m_membershipGrid->EndBatch();
     Thaw();
@@ -205,6 +210,24 @@ PANEL_SETUP_NETCLASSES::~PANEL_SETUP_NETCLASSES()
     m_netclassGrid->Disconnect( wxEVT_GRID_CELL_CHANGING,
                                 wxGridEventHandler( PANEL_SETUP_NETCLASSES::OnNetclassGridCellChanging ),
                                 nullptr, this );
+
+    m_frame->Unbind( UNITS_CHANGED, &PANEL_SETUP_NETCLASSES::onUnitsChanged, this );
+}
+
+
+void PANEL_SETUP_NETCLASSES::onUnitsChanged( wxCommandEvent& aEvent )
+{
+    NETCLASSES  tempNetClasses;
+    NETCLASSES* saveNetClasses = m_netclasses;
+
+    m_netclasses = &tempNetClasses;       // No, address of stack var does not escape function
+
+    TransferDataFromWindow();
+    TransferDataToWindow();
+
+    m_netclasses = saveNetClasses;
+
+    aEvent.Skip();
 }
 
 
@@ -251,7 +274,7 @@ bool PANEL_SETUP_NETCLASSES::TransferDataToWindow()
     m_netclassGrid->AppendRows((int) m_netclasses->GetCount() + 1 ); // + 1 for default netclass
 
     // enter the Default NETCLASS.
-    netclassToGridRow( m_Parent->GetUserUnits(), m_netclassGrid, 0, m_netclasses->GetDefault() );
+    netclassToGridRow( m_frame->GetUserUnits(), m_netclassGrid, 0, m_netclasses->GetDefault() );
 
     // make the Default NETCLASS name read-only
     wxGridCellAttr* cellAttr = m_netclassGrid->GetOrCreateCellAttr( 0, GRID_NAME );
@@ -265,7 +288,7 @@ bool PANEL_SETUP_NETCLASSES::TransferDataToWindow()
     {
         NETCLASSPTR netclass = i->second;
 
-        netclassToGridRow( m_Parent->GetUserUnits(), m_netclassGrid, row, netclass );
+        netclassToGridRow( m_frame->GetUserUnits(), m_netclassGrid, row, netclass );
 
         for( const wxString& net : *netclass )
         {
@@ -373,7 +396,7 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
     m_netclasses->Clear();
 
     // Copy the default NetClass:
-    gridRowToNetclass( m_Parent->GetUserUnits(), m_netclassGrid, 0, m_netclasses->GetDefault() );
+    gridRowToNetclass( m_frame->GetUserUnits(), m_netclassGrid, 0, m_netclasses->GetDefault() );
 
     // Copy other NetClasses:
     for( int row = 1; row < m_netclassGrid->GetNumberRows();  ++row )
@@ -382,7 +405,7 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
                                                                                    GRID_NAME ) );
 
         if( m_netclasses->Add( nc ) )
-            gridRowToNetclass( m_Parent->GetUserUnits(), m_netclassGrid, row, nc );
+            gridRowToNetclass( m_frame->GetUserUnits(), m_netclassGrid, row, nc );
     }
 
     // Now read all nets and push them in the corresponding netclass net buffer
@@ -415,7 +438,7 @@ bool PANEL_SETUP_NETCLASSES::validateNetclassName( int aRow, const wxString& aNa
     if( tmp.IsEmpty() )
     {
         wxString msg =  _( "Netclass must have a name." );
-        m_Parent->SetError( msg, this, m_netclassGrid, aRow, GRID_NAME );
+        m_parent->SetError( msg, this, m_netclassGrid, aRow, GRID_NAME );
         return false;
     }
 
@@ -424,7 +447,7 @@ bool PANEL_SETUP_NETCLASSES::validateNetclassName( int aRow, const wxString& aNa
         if( ii != aRow && m_netclassGrid->GetCellValue( ii, GRID_NAME ).CmpNoCase( tmp ) == 0 )
         {
             wxString msg = _( "Netclass name already in use." );
-            m_Parent->SetError( msg, this, m_netclassGrid, focusFirst ? aRow : ii, GRID_NAME );
+            m_parent->SetError( msg, this, m_netclassGrid, focusFirst ? aRow : ii, GRID_NAME );
             return false;
         }
     }
diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp
index cd57003d4d..739dbd40c4 100644
--- a/common/eda_draw_frame.cpp
+++ b/common/eda_draw_frame.cpp
@@ -267,11 +267,20 @@ void EDA_DRAW_FRAME::unitsChangeRefresh()
 
 void EDA_DRAW_FRAME::ToggleUserUnits()
 {
-    SetUserUnits( m_userUnits == EDA_UNITS::INCHES ? EDA_UNITS::MILLIMETRES : EDA_UNITS::INCHES );
-    unitsChangeRefresh();
+    if( m_toolManager->GetTool<COMMON_TOOLS>() )
+    {
+        TOOL_EVENT dummy;
+        m_toolManager->GetTool<COMMON_TOOLS>()->ToggleUnits( dummy );
+    }
+    else
+    {
+        SetUserUnits( m_userUnits == EDA_UNITS::INCHES ? EDA_UNITS::MILLIMETRES
+                                                       : EDA_UNITS::INCHES );
+        unitsChangeRefresh();
 
-    wxCommandEvent e( UNITS_CHANGED );
-    ProcessEventLocally( e );
+        wxCommandEvent e( UNITS_CHANGED );
+        ProcessEventLocally( e );
+    }
 }
 
 
diff --git a/demos/video/video.kicad_pro b/demos/video/video.kicad_pro
index 19cac8c44e..2b7291423f 100644
--- a/demos/video/video.kicad_pro
+++ b/demos/video/video.kicad_pro
@@ -119,7 +119,9 @@
         "use_height_for_length_calcs": true
       },
       "track_widths": [
-        0.0
+        0.0,
+        0.2,
+        0.5
       ],
       "via_dimensions": [
         {
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
index 8ec47b9082..f7fe7ea8a2 100644
--- a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
@@ -37,10 +37,27 @@
 class PIN_TABLE_DATA_MODEL : public wxGridTableBase
 {
 public:
-    PIN_TABLE_DATA_MODEL( EDA_UNITS aUserUnits ) : m_userUnits( aUserUnits ), m_edited( false )
+    PIN_TABLE_DATA_MODEL( SYMBOL_EDIT_FRAME* aFrame ) :
+            m_frame( aFrame ),
+            m_edited( false )
     {
+        m_frame->Bind( UNITS_CHANGED, &PIN_TABLE_DATA_MODEL::onUnitsChanged, this );
     }
 
+    ~PIN_TABLE_DATA_MODEL()
+    {
+        m_frame->Unbind( UNITS_CHANGED, &PIN_TABLE_DATA_MODEL::onUnitsChanged, this );
+    }
+
+    void onUnitsChanged( wxCommandEvent& aEvent )
+    {
+        if( GetView() )
+            GetView()->ForceRefresh();
+
+        aEvent.Skip();
+    }
+
+
     int GetNumberRows() override { return (int) m_rows.size(); }
     int GetNumberCols() override { return COL_COUNT; }
 
@@ -70,7 +87,7 @@ public:
 
     wxString GetValue( int aRow, int aCol ) override
     {
-        return GetValue( m_rows[ aRow ], aCol, m_userUnits );
+        return GetValue( m_rows[ aRow ], aCol, m_frame->GetUserUnits() );
     }
 
     static wxString GetValue( const LIB_PINS& pins, int aCol, EDA_UNITS aUserUnits )
@@ -181,25 +198,25 @@ public:
                 break;
 
             case COL_NUMBER_SIZE:
-                pin->SetNumberTextSize( ValueFromString( m_userUnits, aValue ) );
+                pin->SetNumberTextSize( ValueFromString( m_frame->GetUserUnits(), aValue ) );
                 break;
 
             case COL_NAME_SIZE:
-                pin->SetNameTextSize( ValueFromString( m_userUnits, aValue ) );
+                pin->SetNameTextSize( ValueFromString( m_frame->GetUserUnits(), aValue ) );
                 break;
 
             case COL_LENGTH:
-                pin->SetLength( ValueFromString( m_userUnits, aValue ) );
+                pin->SetLength( ValueFromString( m_frame->GetUserUnits(), aValue ) );
                 break;
 
             case COL_POSX:
-                pin->SetPosition( wxPoint( ValueFromString( m_userUnits, aValue ),
+                pin->SetPosition( wxPoint( ValueFromString( m_frame->GetUserUnits(), aValue ),
                                            pin->GetPosition().y ) );
                 break;
 
             case COL_POSY:
                 pin->SetPosition( wxPoint( pin->GetPosition().x,
-                                           ValueFromString( m_userUnits, aValue ) ) );
+                                           ValueFromString( m_frame->GetUserUnits(), aValue ) ) );
                 break;
 
             case COL_VISIBLE:
@@ -332,7 +349,7 @@ public:
         std::sort( m_rows.begin(), m_rows.end(),
                    [ aSortCol, ascending, this ]( const LIB_PINS& lhs, const LIB_PINS& rhs ) -> bool
                    {
-                       return compare( lhs, rhs, aSortCol, ascending, m_userUnits );
+                       return compare( lhs, rhs, aSortCol, ascending, m_frame->GetUserUnits() );
                    } );
     }
 
@@ -406,13 +423,15 @@ private:
         }
     }
 
+private:
+    SYMBOL_EDIT_FRAME*    m_frame;
+
     // Because the rows of the grid can either be a single pin or a group of pins, the
     // data model is a 2D vector.  If we're in the single pin case, each row's LIB_PINS
     // contains only a single pin.
     std::vector<LIB_PINS> m_rows;
 
-    EDA_UNITS m_userUnits;
-    bool      m_edited;
+    bool                  m_edited;
 };
 
 
@@ -422,7 +441,7 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( SYMBOL_EDIT_FRAME* parent,
         m_editFrame( parent ),
         m_part( aSymbol )
 {
-    m_dataModel = new PIN_TABLE_DATA_MODEL( GetUserUnits() );
+    m_dataModel = new PIN_TABLE_DATA_MODEL( m_editFrame );
 
     // Save original columns widths so we can do proportional sizing.
     for( int i = 0; i < COL_COUNT; ++i )
diff --git a/eeschema/dialogs/dialog_schematic_setup.cpp b/eeschema/dialogs/dialog_schematic_setup.cpp
index 947557639b..55a50a944f 100644
--- a/eeschema/dialogs/dialog_schematic_setup.cpp
+++ b/eeschema/dialogs/dialog_schematic_setup.cpp
@@ -56,7 +56,7 @@ DIALOG_SCHEMATIC_SETUP::DIALOG_SCHEMATIC_SETUP( SCH_EDIT_FRAME* aFrame ) :
 
     m_textVars = new PANEL_TEXT_VARIABLES( m_treebook, &Prj() );
 
-    m_netclasses = new PANEL_SETUP_NETCLASSES( this, &project.NetSettings().m_NetClasses,
+    m_netclasses = new PANEL_SETUP_NETCLASSES( this, aFrame, &project.NetSettings().m_NetClasses,
                                                schematic.GetNetClassAssignmentCandidates(), true );
 
     /*
diff --git a/eeschema/fields_grid_table.cpp b/eeschema/fields_grid_table.cpp
index 0af658a4d8..9f437c7ed4 100644
--- a/eeschema/fields_grid_table.cpp
+++ b/eeschema/fields_grid_table.cpp
@@ -51,7 +51,6 @@ FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* a
                                          WX_GRID* aGrid, LIB_SYMBOL* aSymbol ) :
         m_frame( aFrame ),
         m_dialog( aDialog ),
-        m_userUnits( aDialog->GetUserUnits() ),
         m_grid( aGrid ),
         m_parentType( SCH_SYMBOL_T ),
         m_mandatoryFieldCount( MANDATORY_FIELDS ),
@@ -73,7 +72,6 @@ FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* a
                                          WX_GRID* aGrid, SCH_SHEET* aSheet ) :
         m_frame( aFrame ),
         m_dialog( aDialog ),
-        m_userUnits( aDialog->GetUserUnits() ),
         m_grid( aGrid ),
         m_parentType( SCH_SHEET_T ),
         m_mandatoryFieldCount( SHEET_MANDATORY_FIELDS ),
@@ -170,6 +168,8 @@ void FIELDS_GRID_TABLE<T>::initGrid( WX_GRID* aGrid )
     m_orientationAttr = new wxGridCellAttr;
     m_orientationAttr->SetEditor( new wxGridCellChoiceEditor( orientationNames ) );
     m_orientationAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
+
+    m_frame->Bind( UNITS_CHANGED, &FIELDS_GRID_TABLE<T>::onUnitsChanged, this );
 }
 
 
@@ -188,6 +188,18 @@ FIELDS_GRID_TABLE<T>::~FIELDS_GRID_TABLE()
     m_vAlignAttr->DecRef();
     m_hAlignAttr->DecRef();
     m_orientationAttr->DecRef();
+
+    m_frame->Unbind( UNITS_CHANGED, &FIELDS_GRID_TABLE<T>::onUnitsChanged, this );
+}
+
+
+template <class T>
+void FIELDS_GRID_TABLE<T>::onUnitsChanged( wxCommandEvent& aEvent )
+{
+    if( GetView() )
+        GetView()->ForceRefresh();
+
+    aEvent.Skip();
 }
 
 
@@ -416,7 +428,7 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
         return StringFromBool( field.IsBold() );
 
     case FDC_TEXT_SIZE:
-        return StringFromValue( m_userUnits, field.GetTextSize().GetHeight(), true );
+        return StringFromValue( m_frame->GetUserUnits(), field.GetTextSize().GetHeight(), true );
 
     case FDC_ORIENTATION:
         switch ( (int) field.GetTextAngle() )
@@ -428,10 +440,10 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
         break;
 
     case FDC_POSX:
-        return StringFromValue( m_userUnits, field.GetTextPos().x, true );
+        return StringFromValue( m_frame->GetUserUnits(), field.GetTextPos().x, true );
 
     case FDC_POSY:
-        return StringFromValue( m_userUnits, field.GetTextPos().y, true );
+        return StringFromValue( m_frame->GetUserUnits(), field.GetTextPos().y, true );
 
     default:
         // we can't assert here because wxWidgets sometimes calls this without checking
@@ -534,8 +546,8 @@ void FIELDS_GRID_TABLE<T>::SetValue( int aRow, int aCol, const wxString &aValue
         break;
 
     case FDC_TEXT_SIZE:
-        field.SetTextSize( wxSize( ValueFromString( m_userUnits, aValue ),
-                                   ValueFromString( m_userUnits, aValue ) ) );
+        field.SetTextSize( wxSize( ValueFromString( m_frame->GetUserUnits(), aValue ),
+                                   ValueFromString( m_frame->GetUserUnits(), aValue ) ) );
         break;
 
     case FDC_ORIENTATION:
@@ -551,9 +563,9 @@ void FIELDS_GRID_TABLE<T>::SetValue( int aRow, int aCol, const wxString &aValue
     case FDC_POSY:
         pos = field.GetTextPos();
         if( aCol == FDC_POSX )
-            pos.x = ValueFromString( m_userUnits, aValue );
+            pos.x = ValueFromString( m_frame->GetUserUnits(), aValue );
         else
-            pos.y = ValueFromString( m_userUnits, aValue );
+            pos.y = ValueFromString( m_frame->GetUserUnits(), aValue );
         field.SetTextPos( pos );
         break;
 
diff --git a/eeschema/fields_grid_table.h b/eeschema/fields_grid_table.h
index 53d5e8fa33..c01b321956 100644
--- a/eeschema/fields_grid_table.h
+++ b/eeschema/fields_grid_table.h
@@ -104,10 +104,11 @@ public:
 protected:
     void initGrid( WX_GRID* aGrid );
 
+    void onUnitsChanged( wxCommandEvent& aEvent );
+
 private:
     SCH_BASE_FRAME* m_frame;
     DIALOG_SHIM*    m_dialog;
-    EDA_UNITS       m_userUnits;
     WX_GRID*        m_grid;
     KICAD_T         m_parentType;
     int             m_mandatoryFieldCount;
diff --git a/include/dialogs/panel_setup_netclasses.h b/include/dialogs/panel_setup_netclasses.h
index b74dcad6e7..307cb5a0f5 100644
--- a/include/dialogs/panel_setup_netclasses.h
+++ b/include/dialogs/panel_setup_netclasses.h
@@ -35,7 +35,7 @@ class NETCLASSES;
 class PANEL_SETUP_NETCLASSES : public PANEL_SETUP_NETCLASSES_BASE
 {
 public:
-    PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, NETCLASSES* aNetclasses,
+    PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_FRAME* aFrame, NETCLASSES* aNetclasses,
                             const std::vector<wxString>& aNetNames, bool isEEschema );
     ~PANEL_SETUP_NETCLASSES( ) override;
 
@@ -60,6 +60,8 @@ private:
     void OnAssignAll( wxCommandEvent& event ) override { doAssignments( true ); }
     void OnAssignSelected( wxCommandEvent& event ) override { doAssignments( false ); }
 
+    void onUnitsChanged( wxCommandEvent& aEvent );
+
     bool validateNetclassName( int aRow, const wxString& aName, bool focusFirst = true );
 
     void rebuildNetclassDropdowns();
@@ -71,7 +73,8 @@ private:
     void AdjustNetclassGridColumns( int aWidth );
     void AdjustMembershipGridColumns( int aWidth );
 
-    PAGED_DIALOG*         m_Parent;
+    EDA_DRAW_FRAME*       m_frame;
+    PAGED_DIALOG*         m_parent;
     NETCLASSES*           m_netclasses;
     std::vector<wxString> m_netNames;
 
diff --git a/pcbnew/dialogs/dialog_board_setup.cpp b/pcbnew/dialogs/dialog_board_setup.cpp
index 03d56d1d0b..5261ebf224 100644
--- a/pcbnew/dialogs/dialog_board_setup.cpp
+++ b/pcbnew/dialogs/dialog_board_setup.cpp
@@ -68,7 +68,7 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
     m_severities = new PANEL_SETUP_SEVERITIES( this, DRC_ITEM::GetItemsWithSeverities(),
                                                bds.m_DRCSeverities );
 
-    m_netclasses = new PANEL_SETUP_NETCLASSES( this, &bds.GetNetClasses(),
+    m_netclasses = new PANEL_SETUP_NETCLASSES( this, aFrame, &bds.GetNetClasses(),
                                                board->GetNetClassAssignmentCandidates(), false );
 
     m_textVars = new PANEL_TEXT_VARIABLES( m_treebook, &Prj() );
diff --git a/pcbnew/dialogs/dialog_footprint_properties.cpp b/pcbnew/dialogs/dialog_footprint_properties.cpp
index 8f55f439a8..a64885fd3a 100644
--- a/pcbnew/dialogs/dialog_footprint_properties.cpp
+++ b/pcbnew/dialogs/dialog_footprint_properties.cpp
@@ -81,7 +81,7 @@ DIALOG_FOOTPRINT_PROPERTIES::DIALOG_FOOTPRINT_PROPERTIES( PCB_EDIT_FRAME* aParen
     for( size_t i = 0; i < m_NoteBook->GetPageCount(); ++i )
    	    m_macHack.push_back( true );
 
-    m_texts = new FP_TEXT_GRID_TABLE( m_units, m_frame );
+    m_texts = new FP_TEXT_GRID_TABLE( m_frame );
 
     m_delayedErrorMessage = wxEmptyString;
     m_delayedFocusGrid = nullptr;
diff --git a/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp b/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp
index 5a0dd4ff62..36749fa09e 100644
--- a/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp
+++ b/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp
@@ -74,7 +74,7 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR(
     m_3dPanel = new PANEL_FP_PROPERTIES_3D_MODEL( m_frame, m_footprint, this, m_NoteBook );
     m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
 
-    m_texts = new FP_TEXT_GRID_TABLE( m_units, m_frame );
+    m_texts = new FP_TEXT_GRID_TABLE( m_frame );
 
     m_delayedErrorMessage = wxEmptyString;
     m_delayedFocusCtrl = nullptr;
diff --git a/pcbnew/dialogs/panel_setup_text_and_graphics.cpp b/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
index f86ad07831..9f6a04ddb2 100644
--- a/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
+++ b/pcbnew/dialogs/panel_setup_text_and_graphics.cpp
@@ -91,6 +91,8 @@ PANEL_SETUP_TEXT_AND_GRAPHICS::PANEL_SETUP_TEXT_AND_GRAPHICS( PAGED_DIALOG* aPar
     }
 
     m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
+
+    m_Frame->Bind( UNITS_CHANGED, &PANEL_SETUP_TEXT_AND_GRAPHICS::onUnitsChanged, this );
 }
 
 
@@ -98,6 +100,24 @@ PANEL_SETUP_TEXT_AND_GRAPHICS::~PANEL_SETUP_TEXT_AND_GRAPHICS()
 {
     // destroy GRID_TRICKS before m_grid.
     m_grid->PopEventHandler( true );
+
+    m_Frame->Unbind( UNITS_CHANGED, &PANEL_SETUP_TEXT_AND_GRAPHICS::onUnitsChanged, this );
+}
+
+
+void PANEL_SETUP_TEXT_AND_GRAPHICS::onUnitsChanged( wxCommandEvent& aEvent )
+{
+    BOARD_DESIGN_SETTINGS  tempBDS( nullptr, "dummy" );
+    BOARD_DESIGN_SETTINGS* saveBDS = m_BrdSettings;
+
+    m_BrdSettings = &tempBDS;       // No, address of stack var does not escape function
+
+    TransferDataFromWindow();
+    TransferDataToWindow();
+
+    m_BrdSettings = saveBDS;
+
+    aEvent.Skip();
 }
 
 
diff --git a/pcbnew/dialogs/panel_setup_text_and_graphics.h b/pcbnew/dialogs/panel_setup_text_and_graphics.h
index 61282d7714..fdc737827c 100644
--- a/pcbnew/dialogs/panel_setup_text_and_graphics.h
+++ b/pcbnew/dialogs/panel_setup_text_and_graphics.h
@@ -49,6 +49,9 @@ public:
 private:
     int getGridValue( int aRow, int aCol );
 
+    void onUnitsChanged( wxCommandEvent& aEvent );
+
+private:
     PAGED_DIALOG*           m_Parent;
     PCB_EDIT_FRAME*         m_Frame;
     BOARD_DESIGN_SETTINGS*  m_BrdSettings;
diff --git a/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp b/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp
index 1984cc2ae9..e19de1f454 100644
--- a/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp
+++ b/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp
@@ -100,16 +100,38 @@ PANEL_SETUP_TRACKS_AND_VIAS::PANEL_SETUP_TRACKS_AND_VIAS( PAGED_DIALOG* aParent,
             curr_grid->SetColSize( col,best_w );
         }
     }
+
+    m_Frame->Bind( UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this );
 }
 
+
 PANEL_SETUP_TRACKS_AND_VIAS::~PANEL_SETUP_TRACKS_AND_VIAS()
 {
     // Delete the GRID_TRICKS.
     m_trackWidthsGrid->PopEventHandler( true );
     m_viaSizesGrid->PopEventHandler( true );
     m_diffPairsGrid->PopEventHandler( true );
+
+    m_Frame->Unbind( UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this );
 }
 
+
+void PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged( wxCommandEvent& aEvent )
+{
+    BOARD_DESIGN_SETTINGS  tempBDS( nullptr, "dummy" );
+    BOARD_DESIGN_SETTINGS* saveBDS = m_BrdSettings;
+
+    m_BrdSettings = &tempBDS;       // No, address of stack var does not escape function
+
+    TransferDataFromWindow();
+    TransferDataToWindow();
+
+    m_BrdSettings = saveBDS;
+
+    aEvent.Skip();
+}
+
+
 bool PANEL_SETUP_TRACKS_AND_VIAS::TransferDataToWindow()
 {
     m_trackWidthsGrid->ClearRows();
diff --git a/pcbnew/dialogs/panel_setup_tracks_and_vias.h b/pcbnew/dialogs/panel_setup_tracks_and_vias.h
index 2ce3a6e253..bb0b024f8c 100644
--- a/pcbnew/dialogs/panel_setup_tracks_and_vias.h
+++ b/pcbnew/dialogs/panel_setup_tracks_and_vias.h
@@ -58,6 +58,8 @@ protected:
     void OnAddDiffPairsClick( wxCommandEvent& event ) override;
     void OnRemoveDiffPairsClick( wxCommandEvent& event ) override;
 
+    void onUnitsChanged( wxCommandEvent& aEvent );
+
     void AppendTrackWidth( const int aWidth );
     void AppendViaSize( const int aSize, const int aDrill );
     void AppendDiffPairs( const int aWidth, const int aGap, const int aViaGap );
diff --git a/pcbnew/fp_text_grid_table.cpp b/pcbnew/fp_text_grid_table.cpp
index b365638006..8797e13455 100644
--- a/pcbnew/fp_text_grid_table.cpp
+++ b/pcbnew/fp_text_grid_table.cpp
@@ -27,6 +27,7 @@
 #include <widgets/grid_icon_text_helpers.h>
 #include <widgets/grid_combobox.h>
 #include <trigo.h>
+#include <pcb_base_frame.h>
 #include "grid_layer_box_helpers.h"
 
 enum
@@ -39,8 +40,8 @@ enum
 wxArrayString g_menuOrientations;
 
 
-FP_TEXT_GRID_TABLE::FP_TEXT_GRID_TABLE( EDA_UNITS aUserUnits, PCB_BASE_FRAME* aFrame )
-        : m_userUnits( aUserUnits ), m_frame( aFrame )
+FP_TEXT_GRID_TABLE::FP_TEXT_GRID_TABLE( PCB_BASE_FRAME* aFrame ) :
+        m_frame( aFrame )
 {
     // Build the column attributes.
 
@@ -70,6 +71,8 @@ FP_TEXT_GRID_TABLE::FP_TEXT_GRID_TABLE( EDA_UNITS aUserUnits, PCB_BASE_FRAME* aF
     m_layerColAttr = new wxGridCellAttr;
     m_layerColAttr->SetRenderer( new GRID_CELL_LAYER_RENDERER( m_frame ) );
     m_layerColAttr->SetEditor( new GRID_CELL_LAYER_SELECTOR( m_frame, {} ) );
+
+    m_frame->Bind( UNITS_CHANGED, &FP_TEXT_GRID_TABLE::onUnitsChanged, this );
 }
 
 
@@ -79,6 +82,17 @@ FP_TEXT_GRID_TABLE::~FP_TEXT_GRID_TABLE()
     m_boolColAttr->DecRef();
     m_orientationColAttr->DecRef();
     m_layerColAttr->DecRef();
+
+    m_frame->Unbind( UNITS_CHANGED, &FP_TEXT_GRID_TABLE::onUnitsChanged, this );
+}
+
+
+void FP_TEXT_GRID_TABLE::onUnitsChanged( wxCommandEvent& aEvent )
+{
+    if( GetView() )
+        GetView()->ForceRefresh();
+
+    aEvent.Skip();
 }
 
 
@@ -190,13 +204,13 @@ wxString FP_TEXT_GRID_TABLE::GetValue( int aRow, int aCol )
         return text.GetText();
 
     case FPT_WIDTH:
-        return StringFromValue( m_userUnits, text.GetTextWidth(), true );
+        return StringFromValue( m_frame->GetUserUnits(), text.GetTextWidth(), true );
 
     case FPT_HEIGHT:
-        return StringFromValue( m_userUnits, text.GetTextHeight(), true );
+        return StringFromValue( m_frame->GetUserUnits(), text.GetTextHeight(), true );
 
     case FPT_THICKNESS:
-        return StringFromValue( m_userUnits, text.GetTextThickness(), true );
+        return StringFromValue( m_frame->GetUserUnits(), text.GetTextThickness(), true );
 
     case FPT_LAYER:
         return text.GetLayerName();
@@ -206,10 +220,10 @@ wxString FP_TEXT_GRID_TABLE::GetValue( int aRow, int aCol )
                                 true );
 
     case FPT_XOFFSET:
-        return StringFromValue( m_userUnits, text.GetPos0().x, true );
+        return StringFromValue( m_frame->GetUserUnits(), text.GetPos0().x, true );
 
     case FPT_YOFFSET:
-        return StringFromValue( m_userUnits, text.GetPos0().y, true );
+        return StringFromValue( m_frame->GetUserUnits(), text.GetPos0().y, true );
 
     default:
         // we can't assert here because wxWidgets sometimes calls this without checking
@@ -261,14 +275,14 @@ void FP_TEXT_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
         break;
 
     case FPT_WIDTH:
-        text.SetTextWidth( ValueFromString( m_userUnits, aValue ) );
+        text.SetTextWidth( ValueFromString( m_frame->GetUserUnits(), aValue ) );
         break;
 
     case FPT_HEIGHT:
-        text.SetTextHeight( ValueFromString( m_userUnits, aValue ) );
+        text.SetTextHeight( ValueFromString( m_frame->GetUserUnits(), aValue ) );
         break;
 
-    case FPT_THICKNESS:text.SetTextThickness( ValueFromString( m_userUnits, aValue ) );
+    case FPT_THICKNESS:text.SetTextThickness( ValueFromString( m_frame->GetUserUnits(), aValue ) );
         break;
 
     case FPT_ORIENTATION:
@@ -281,9 +295,9 @@ void FP_TEXT_GRID_TABLE::SetValue( int aRow, int aCol, const wxString &aValue )
         pos = text.GetPos0();
 
         if( aCol == FPT_XOFFSET )
-            pos.x = ValueFromString( m_userUnits, aValue );
+            pos.x = ValueFromString( m_frame->GetUserUnits(), aValue );
         else
-            pos.y = ValueFromString( m_userUnits, aValue );
+            pos.y = ValueFromString( m_frame->GetUserUnits(), aValue );
 
         text.SetPos0( pos );
         text.SetDrawCoord();
diff --git a/pcbnew/fp_text_grid_table.h b/pcbnew/fp_text_grid_table.h
index ec8e965e8a..5cd823f975 100644
--- a/pcbnew/fp_text_grid_table.h
+++ b/pcbnew/fp_text_grid_table.h
@@ -54,7 +54,7 @@ enum FP_TEXT_COL_ORDER
 class FP_TEXT_GRID_TABLE : public wxGridTableBase, public std::vector<FP_TEXT>
 {
 public:
-    FP_TEXT_GRID_TABLE( EDA_UNITS userUnits, PCB_BASE_FRAME* aFrame );
+    FP_TEXT_GRID_TABLE( PCB_BASE_FRAME* aFrame );
     ~FP_TEXT_GRID_TABLE();
 
     int GetNumberRows() override { return (int) size(); }
@@ -80,8 +80,10 @@ public:
     void SetValueAsBool( int aRow, int aCol, bool aValue ) override;
     void SetValueAsLong( int aRow, int aCol, long aValue ) override;
 
+protected:
+    void onUnitsChanged( wxCommandEvent& aEvent );
+
 private:
-    EDA_UNITS       m_userUnits;
     PCB_BASE_FRAME* m_frame;
 
     wxGridCellAttr* m_readOnlyAttr;