diff --git a/src/dlangui/core/events.d b/src/dlangui/core/events.d
index 33be614f..5b1603fc 100644
--- a/src/dlangui/core/events.d
+++ b/src/dlangui/core/events.d
@@ -164,8 +164,10 @@ class Action {
         _id = a._id;
         _label = a._label;
         _iconId = a._iconId;
-        _state = a._state.clone();
-        _defaultState = a._defaultState.clone();
+        if (a._state)
+            _state = a._state.clone();
+        if (a._defaultState)
+            _defaultState = a._defaultState.clone();
         _accelerators.length = a._accelerators.length;
         for(int i = 0; i < _accelerators.length; i++)
             _accelerators[i] = a._accelerators[i];
diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d
index 04bee0a4..09b2d1a2 100644
--- a/src/dlangui/platforms/common/platform.d
+++ b/src/dlangui/platforms/common/platform.d
@@ -818,6 +818,14 @@ class Window {
         return res || processed || _mainWidget.needDraw;
     }
 
+    /// calls update actions recursively
+    protected void dispatchWidgetUpdateActionStateRecursive(Widget root) {
+        if (root is null)
+            return;
+        root.updateActionState(true);
+        for (int i = 0; i < root.childCount; i++)
+            dispatchWidgetUpdateActionStateRecursive(root.child(i));
+    }
     /// checks content widgets for necessary redraw and/or layout
     protected void checkUpdateNeeded(Widget root, ref bool needDraw, ref bool needLayout, ref bool animationActive) {
         if (root is null)
@@ -842,6 +850,14 @@ class Window {
 	}
     /// checks content widgets for necessary redraw and/or layout
     bool checkUpdateNeeded(ref bool needDraw, ref bool needLayout, ref bool animationActive) {
+        if (_actionsUpdateRequested) {
+            // call update action check - as requested
+            if (_mainWidget !is null)
+                dispatchWidgetUpdateActionStateRecursive(_mainWidget);
+            foreach(p; _popups)
+                dispatchWidgetUpdateActionStateRecursive(p);
+            _actionsUpdateRequested = false;
+        }
         needDraw = needLayout = animationActive = false;
         if (_mainWidget is null)
             return false;
diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d
index 005a8891..76fe7cf8 100644
--- a/src/dlangui/widgets/widget.d
+++ b/src/dlangui/widgets/widget.d
@@ -626,23 +626,48 @@ class Widget {
     @property void action(const Action action) { _action = action.clone; }
     /// action to emit on click
     @property void action(Action action) { _action = action; }
-    /// ask for update state of some action (unles force=true, checks window flag 
-    void updateActionState(Action a, bool force = false) {
+    /// ask for update state of some action (unles force=true, checks window flag actionsUpdateRequested), returns true if action state is changed
+    bool updateActionState(Action a, bool force = false) {
         if (Window w = window) {
             if (!force && !w.actionsUpdateRequested())
-                return;
+                return false;
+            const ActionState oldState = a.state;
             if (w.dispatchActionStateRequest(a, this)) {
                 // state is updated
             } else {
                 a.state = a.defaultState;
             }
+            if (a.state != oldState)
+                return true;
         }
+        return false;
     }
     /// call to update state for action (if action is assigned for widget)
     void updateActionState(bool force = false) {
         if (!_action)
             return;
-        updateActionState(_action, force);
+        if (updateActionState(_action, force))
+            handleActionStateChanged();
+    }
+    /// called when state of action assigned on widget is changed
+    void handleActionStateChanged() {
+        // override to update enabled state, visibility and checked state
+        // default processing: copy flags to this widget
+        updateStateFromAction(_action);
+    }
+    /// apply enabled, visibile and checked state for this widget from action's state
+    void updateStateFromAction(Action a) {
+        const ActionState s = a.state;
+        if (s.enabled != enabled) {
+            enabled = s.enabled;
+        }
+        if (s.checked != checked) {
+            checked = s.checked;
+        }
+        bool v = _visibility == Visibility.Visible;
+        if (s.visible != v) {
+            visibility = s.visible ? Visibility.Visible : Visibility.Gone;
+        }
     }
 
     protected bool _focusGroup;