View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002670 | NoesisGUI | Unity3D | public | 2023-08-21 08:01 | 2023-08-21 16:12 |
Reporter | ckfinite | Assigned To | sfernandez | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | assigned | Resolution | open | ||
Product Version | 3.2 | ||||
Summary | 0002670: Buttons that invoke a RoutedCommand don't refresh their CanExecute when RaiseCanExecuteChanged is called. | ||||
Description | Buttons that trigger Custom RoutedCommands do not refresh their visual or logical state by invoking CanExecute after RaiseCanExecuteChanged is called on the base RoutedCommand. | ||||
Steps To Reproduce | Suppose that we have the XAML [code] <Button Command="{l:CustomStatic l:MyTarget.MyCustomCommand}"> <!--- some suitable content goes here --> </Button> [/code] Note that we reimplemented the x:Static MarkupExtension as the provided x:Static implementation (despite the documentation) doesn't actually support custom RoutedCommands. and an implementation: [code] public class MyTarget : UserControl { public static RoutedCommand MyCustomCommand { get; } = new RoutedCommand(); public MyTarget() { var binding = new CommandBinding(); binding.Command = MyCustomCommand; binding.CanExecute += MyCanExecute; binding.Executed += MyExecute; CommandBindings.Add(binding); } private bool testCanExecute = true; private void MyExecute(object sender, ExecutedRoutedEventArgs e) { Debug.Log($"MyExecute called - current value {testCanExecute}!"); testCanExecute = !testCanExecute; MyCustomCommand.RaiseCanExecuteChanged(); Debug.Log($"MyExecute exited - current value {testCanExecute}!"); } private void MyCanExecute(object sender, CanExecuteRoutedEventArgs e) { Debug.Log($"MyCanExecute called - current value {testCanExecute}!"); e.CanExecute = testCanExecute; } } [/code] and run the game, the button is (as expected) initially enabled. The log begins by showing several invocations of MyCanExecute with the initial (true) value as the button starts up. Once pressed, it calls MyCanExecute: [code] MyCanExecute called - current value True! UnityEngine.Debug:Log (object) MyTarget:MyCanExecute (object,Noesis.CanExecuteRoutedEventArgs) (at Assets/Scripts/Noesis/Components/Controls/Window.cs:525) Noesis.CommandBinding:RaiseCanExecute (intptr,intptr,intptr) (at Packages/NoesisGUI/Runtime/API/Proxies/CommandBinding.cs:134) Noesis.View:MouseButtonUp (int,int,Noesis.MouseButton) (at Packages/NoesisGUI/Runtime/API/Core/View.cs:215) NoesisView:ProcessEvent (UnityEngine.Event,bool,bool) (at Packages/NoesisGUI/Runtime/NoesisView.cs:1711) NoesisView:OnGUI () (at Packages/NoesisGUI/Runtime/NoesisView.cs:1808) [/code] folowed by CanExecute: [code] MyExecute called - current value True! UnityEngine.Debug:Log (object) MyTarget:MyExecute (object,Noesis.ExecutedRoutedEventArgs) (at Assets/Scripts/Noesis/Components/Controls/Window.cs:518) Noesis.CommandBinding:RaiseExecuted (intptr,intptr,intptr) (at Packages/NoesisGUI/Runtime/API/Proxies/CommandBinding.cs:246) Noesis.View:MouseButtonUp (int,int,Noesis.MouseButton) (at Packages/NoesisGUI/Runtime/API/Core/View.cs:215) NoesisView:ProcessEvent (UnityEngine.Event,bool,bool) (at Packages/NoesisGUI/Runtime/NoesisView.cs:1711) NoesisView:OnGUI () (at Packages/NoesisGUI/Runtime/NoesisView.cs:1808) [/code] which then toggles the value of testCanExecute and invokes RaiseCanExecuteChanged. However, in spite of the call to RaiseCanExecuteChanged, no intervening invocation of MyCanExecute occurs before the final log from MyExecute [code] MyExecute exited - current value False! UnityEngine.Debug:Log (object) MyTarget:MyExecute (object,Noesis.ExecutedRoutedEventArgs) (at Assets/Scripts/Noesis/Components/Controls/Window.cs:521) Noesis.CommandBinding:RaiseExecuted (intptr,intptr,intptr) (at Packages/NoesisGUI/Runtime/API/Proxies/CommandBinding.cs:246) Noesis.View:MouseButtonUp (int,int,Noesis.MouseButton) (at Packages/NoesisGUI/Runtime/API/Core/View.cs:215) NoesisView:ProcessEvent (UnityEngine.Event,bool,bool) (at Packages/NoesisGUI/Runtime/NoesisView.cs:1711) NoesisView:OnGUI () (at Packages/NoesisGUI/Runtime/NoesisView.cs:1808) [/code] As a result, the button remains visually enabled despite the command no longer being executable. MyCanExecute is utilized to check whether the command can be executed when the button is pressed again and prevents additional events from being spawned but this state is not visually reflected. | ||||
Tags | No tags attached. | ||||
Platform | Any | ||||