diff --git a/samples/BehaviorsTestApplication/Views/Pages/ExecuteScriptActionView.axaml b/samples/BehaviorsTestApplication/Views/Pages/ExecuteScriptActionView.axaml index f6ca6a10f..3a88f04c9 100644 --- a/samples/BehaviorsTestApplication/Views/Pages/ExecuteScriptActionView.axaml +++ b/samples/BehaviorsTestApplication/Views/Pages/ExecuteScriptActionView.axaml @@ -9,20 +9,28 @@ - - + - - + diff --git a/src/Avalonia.Xaml.Interactions.Scripting/ExecuteScriptAction.cs b/src/Avalonia.Xaml.Interactions.Scripting/ExecuteScriptAction.cs index 6f41913d6..b9fc0eaf8 100644 --- a/src/Avalonia.Xaml.Interactions.Scripting/ExecuteScriptAction.cs +++ b/src/Avalonia.Xaml.Interactions.Scripting/ExecuteScriptAction.cs @@ -1,9 +1,13 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; using Avalonia.Threading; using Microsoft.CodeAnalysis.CSharp.Scripting; using Avalonia.Xaml.Interactivity; +using Microsoft.CodeAnalysis.Scripting; namespace Avalonia.Xaml.Interactions.Scripting; @@ -13,6 +17,21 @@ namespace Avalonia.Xaml.Interactions.Scripting; [RequiresUnreferencedCode("This functionality is not compatible with trimming.")] public class ExecuteScriptAction : StyledElementAction { + private static string[] s_imports = [ + "System", + "System.Collections.Generic", + "System.Linq", + "Avalonia", + "Avalonia.Collections", + "Avalonia.Controls", + "Avalonia.Interactivity", + "Avalonia.Metadata", + "Avalonia.LogicalTree", + "Avalonia.Reactive", + "Avalonia.Input", + "Avalonia.Markup.Xaml" + ]; + /// /// Identifies the avalonia property. /// @@ -28,27 +47,63 @@ public string? Script set => SetValue(ScriptProperty, value); } + /// + /// Run script using Dispatcher.UIThread.InvokeAsync instead Task.Run. + /// + public bool UseDispatcher { get; set; } = true; + /// public override object Execute(object? sender, object? parameter) { + if (!IsEnabled) + { + return false; + } + if (string.IsNullOrWhiteSpace(Script)) { return false; } + var script = Script; var globals = new ExecuteScriptActionGlobals(sender, parameter); + var loadedAssemblies = AppDomain.CurrentDomain + .GetAssemblies() + .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) + .ToArray(); - _ = Dispatcher.UIThread.InvokeAsync(async () => + if (UseDispatcher) { - try + _ = Dispatcher.UIThread.InvokeAsync(async () => { - _ = await CSharpScript.EvaluateAsync(Script, globals: globals); - } - catch (Exception ex) + await Run(loadedAssemblies, script, s_imports, globals); + }); + } + else + { + _ = Task.Run(async () => { - Debug.WriteLine($"Script execution failed: {ex.Message}"); - } - }); + await Run(loadedAssemblies, script, s_imports, globals); + }); + } + return true; } + + private static async Task Run( + Assembly[] loadedAssemblies, + string? script, + string[] imports, + ExecuteScriptActionGlobals globals) + { + try + { + var options = ScriptOptions.Default.WithImports(imports).WithReferences(loadedAssemblies); + _ = await CSharpScript.RunAsync(script, options, globals); + } + catch (Exception ex) + { + Debug.WriteLine($"Script execution failed: {ex.Message}"); + } + } }