using a textbox to dispatch a string to LUA

I was wondering if anyone knows how I could go about this?

Basically I have a textBox inside a user control like in Joshua’s example in another thread. I have also added a TextChanged method to the textBox.

What I would like to do is have it so the C# dispatches the textBox’s contents to a LUA function every time it’s updated.

But I can’t seem to figure out how dispatch to LUA inside of the TextChanged method, which is inside the user control object.

The only example in the docs for C# to LUA has it so the C# dispatches to LUA as soon as Corona loads…

We document how to communicate from C# to Lua (and vice-versa) here…

   http://docs.coronalabs.com/daily/coronacards/wp8/communication.html

In your case, what you want to do is store a reference of a CoronaRuntimeEnvironment object to a member variable when your project has been “Loaded”.  With that object, you can then dispatch an event to Lua at any time.  Just be sure to only dispatch events on the main UI thread, because that’s the thread Corona/Lua is running on in WP8, but that shouldn’t be an issue since your TextBox is running on the main UI thread too.

One more thing.  Instead of dispatching the TextBox’s change events to Lua, it might be simpler to handle them in C# instead.  When I presented the popup example, the idea was to also show an OK and Cancel button, like how it is typically done in a popup dialog.  When the end-user taps the OK button, you would then validate your TextBoxes in C#, and if everything is valid, then dispatch the end-user’s input to Lua.  This might make things a lot simpler for you from a coding perspective.

Hi Joshua,

That makes sense. Could you could give me a quick example of the syntax to store the reference of the CoronaRuntimeEnvironment object?

I can’t handle the changes in C# as what my textbox does is sort a listView Widget in my LUA code based on the contents of the textBox.

I’m still a little confused on how I dispatch to LUA with the TextChanged native method. When I added the TextChanged method through the UI manager it automatically defined the method in the MyPopup.xaml file. I’m having trouble seeing how I use that method to trigger a dispatch event from the mainPage.xaml

Here is a quick simple example.  This code will dispatch an event from C# to Lua from a .NET timer.

public partial class MainPage : PhoneApplicationPage { /// \<summary\> /// \<para\>Reference to the Corona runtime environment that is currently active.\</para\> /// \<para\>Will be null if a Corona runtime has not been created yet or has been destroyed.\</para\> /// \</summary\> private CoronaLabs.Corona.WinRT.CoronaRuntimeEnvironment fCoronaRuntimeEnvironment = null; /// \<summary\>Timer used to test C# to Lua communications.\</summary\> private System.Windows.Threading.DispatcherTimer fDispatcherTimer; /// \<summary\>Creates and initializes the main page which hosts the CoronaPanel XAML control.\</summary\> public MainPage() { // Initialize this page's components that were set up via the UI designer. InitializeComponent(); // Set up Corona to automatically start up when the control's Loaded event has been raised. // Note: By default, Corona will run the "main.lua" file in the "Assets\Corona" directory. // You can change the defaults via the CoronaPanel's AutoLaunchSettings property. fCoronaPanel.AutoLaunchEnabled = true; // Set up the CoronaPanel control to render fullscreen via the DrawingSurfaceBackgroundGrid control. // This significantly improves the framerate and is the only means of achieving 60 FPS. fCoronaPanel.BackgroundRenderingEnabled = true; fDrawingSurfaceBackgroundGrid.SetBackgroundContentProvider(fCoronaPanel.BackgroundContentProvider); fDrawingSurfaceBackgroundGrid.SetBackgroundManipulationHandler(fCoronaPanel.BackgroundManipulationHandler); // Create a timer used to dispatch an event from C# to Lua every 1 second. fDispatcherTimer = new System.Windows.Threading.DispatcherTimer(); fDispatcherTimer.Interval = TimeSpan.FromSeconds(1.0); fDispatcherTimer.Tick += OnTimerTick; fDispatcherTimer.Start(); // Add Corona runtime event handlers. fCoronaPanel.Runtime.Loaded += OnCoronaRuntimeLoaded; fCoronaPanel.Runtime.Terminating += OnCoronaRuntimeTerminating; } /// \<summary\> /// Called when a new CoronaRuntimeEnvironment has been created/loaded, /// but before the "main.lua" has been executed. /// \</summary\> /// \<param name="sender"\>The CoronaRuntime object that raised this event.\</param\> /// \<param name="e"\>Event arguments providing the CoronaRuntimeEnvironment that has been created/loaded.\</param\> private void OnCoronaRuntimeLoaded(object sender, CoronaLabs.Corona.WinRT.CoronaRuntimeEventArgs e) { // Keep a reference to the Corona runtime environment that was just created/loaded. fCoronaRuntimeEnvironment = e.CoronaRuntimeEnvironment; } /// \<summary\>Called when the CoronaRuntimeEnvironment is about to be terminated.\</summary\> /// \<param name="sender"\>The CoronaRuntime object that raised this event.\</param\> /// \<param name="e"\>Event arguments providing the CoronaRuntimeEnvironment that is about to be terminated.\</param\> private void OnCoronaRuntimeTerminating(object sender, CoronaLabs.Corona.WinRT.CoronaRuntimeEventArgs e) { // Let go of the Corona runtime environment reference. fCoronaRuntimeEnvironment = null; } /// \<summary\>Called every time "fDispatcherTimer" elapses.\</summary\> /// \<param name="sender"\>The dispatcher timer that raised this event.\</param\> /// \<param name="e"\>Empty event arguments.\</param\> private void OnTimerTick(object sender, EventArgs e) { // Do not continue if a Corona runtime is not running. if (fCoronaRuntimeEnvironment == null) { return; } // Dispatch a "timerTicked" event to Lua. var eventProperties = CoronaLabs.Corona.WinRT.CoronaLuaEventProperties.CreateWithName("timerTicked"); fCoronaRuntimeEnvironment.DispatchEvent(new CoronaLabs.Corona.WinRT.CoronaLuaEventArgs(eventProperties)); } }

The key thing here is that you set up a member variable to hold a reference to the currently loaded CoronaRuntimeEnvironment object via the “Loaded” event and release that reference via the “Terminating” event.  You’ll want to release the reference in the Terminating event so that the memory allocated by Corona can be freed when terminated… plus it’s your app’s clue that the Corona runtime is no longer running (ie:  “applicationExit” was called on it).

And in your case, instead of using a timer’s “Tick” event, you would tie it to a different .NET object’s event such as your TextBox’s events or perhaps your OK button’s “Clicked” event.

Hi Joshua, thank you so much for that! With that example I got it working exactly how I need it to!

Great!  Happy to help.  :slight_smile:

We document how to communicate from C# to Lua (and vice-versa) here…

   http://docs.coronalabs.com/daily/coronacards/wp8/communication.html

In your case, what you want to do is store a reference of a CoronaRuntimeEnvironment object to a member variable when your project has been “Loaded”.  With that object, you can then dispatch an event to Lua at any time.  Just be sure to only dispatch events on the main UI thread, because that’s the thread Corona/Lua is running on in WP8, but that shouldn’t be an issue since your TextBox is running on the main UI thread too.

One more thing.  Instead of dispatching the TextBox’s change events to Lua, it might be simpler to handle them in C# instead.  When I presented the popup example, the idea was to also show an OK and Cancel button, like how it is typically done in a popup dialog.  When the end-user taps the OK button, you would then validate your TextBoxes in C#, and if everything is valid, then dispatch the end-user’s input to Lua.  This might make things a lot simpler for you from a coding perspective.

Hi Joshua,

That makes sense. Could you could give me a quick example of the syntax to store the reference of the CoronaRuntimeEnvironment object?

I can’t handle the changes in C# as what my textbox does is sort a listView Widget in my LUA code based on the contents of the textBox.

I’m still a little confused on how I dispatch to LUA with the TextChanged native method. When I added the TextChanged method through the UI manager it automatically defined the method in the MyPopup.xaml file. I’m having trouble seeing how I use that method to trigger a dispatch event from the mainPage.xaml

Here is a quick simple example.  This code will dispatch an event from C# to Lua from a .NET timer.

public partial class MainPage : PhoneApplicationPage { /// \<summary\> /// \<para\>Reference to the Corona runtime environment that is currently active.\</para\> /// \<para\>Will be null if a Corona runtime has not been created yet or has been destroyed.\</para\> /// \</summary\> private CoronaLabs.Corona.WinRT.CoronaRuntimeEnvironment fCoronaRuntimeEnvironment = null; /// \<summary\>Timer used to test C# to Lua communications.\</summary\> private System.Windows.Threading.DispatcherTimer fDispatcherTimer; /// \<summary\>Creates and initializes the main page which hosts the CoronaPanel XAML control.\</summary\> public MainPage() { // Initialize this page's components that were set up via the UI designer. InitializeComponent(); // Set up Corona to automatically start up when the control's Loaded event has been raised. // Note: By default, Corona will run the "main.lua" file in the "Assets\Corona" directory. // You can change the defaults via the CoronaPanel's AutoLaunchSettings property. fCoronaPanel.AutoLaunchEnabled = true; // Set up the CoronaPanel control to render fullscreen via the DrawingSurfaceBackgroundGrid control. // This significantly improves the framerate and is the only means of achieving 60 FPS. fCoronaPanel.BackgroundRenderingEnabled = true; fDrawingSurfaceBackgroundGrid.SetBackgroundContentProvider(fCoronaPanel.BackgroundContentProvider); fDrawingSurfaceBackgroundGrid.SetBackgroundManipulationHandler(fCoronaPanel.BackgroundManipulationHandler); // Create a timer used to dispatch an event from C# to Lua every 1 second. fDispatcherTimer = new System.Windows.Threading.DispatcherTimer(); fDispatcherTimer.Interval = TimeSpan.FromSeconds(1.0); fDispatcherTimer.Tick += OnTimerTick; fDispatcherTimer.Start(); // Add Corona runtime event handlers. fCoronaPanel.Runtime.Loaded += OnCoronaRuntimeLoaded; fCoronaPanel.Runtime.Terminating += OnCoronaRuntimeTerminating; } /// \<summary\> /// Called when a new CoronaRuntimeEnvironment has been created/loaded, /// but before the "main.lua" has been executed. /// \</summary\> /// \<param name="sender"\>The CoronaRuntime object that raised this event.\</param\> /// \<param name="e"\>Event arguments providing the CoronaRuntimeEnvironment that has been created/loaded.\</param\> private void OnCoronaRuntimeLoaded(object sender, CoronaLabs.Corona.WinRT.CoronaRuntimeEventArgs e) { // Keep a reference to the Corona runtime environment that was just created/loaded. fCoronaRuntimeEnvironment = e.CoronaRuntimeEnvironment; } /// \<summary\>Called when the CoronaRuntimeEnvironment is about to be terminated.\</summary\> /// \<param name="sender"\>The CoronaRuntime object that raised this event.\</param\> /// \<param name="e"\>Event arguments providing the CoronaRuntimeEnvironment that is about to be terminated.\</param\> private void OnCoronaRuntimeTerminating(object sender, CoronaLabs.Corona.WinRT.CoronaRuntimeEventArgs e) { // Let go of the Corona runtime environment reference. fCoronaRuntimeEnvironment = null; } /// \<summary\>Called every time "fDispatcherTimer" elapses.\</summary\> /// \<param name="sender"\>The dispatcher timer that raised this event.\</param\> /// \<param name="e"\>Empty event arguments.\</param\> private void OnTimerTick(object sender, EventArgs e) { // Do not continue if a Corona runtime is not running. if (fCoronaRuntimeEnvironment == null) { return; } // Dispatch a "timerTicked" event to Lua. var eventProperties = CoronaLabs.Corona.WinRT.CoronaLuaEventProperties.CreateWithName("timerTicked"); fCoronaRuntimeEnvironment.DispatchEvent(new CoronaLabs.Corona.WinRT.CoronaLuaEventArgs(eventProperties)); } }

The key thing here is that you set up a member variable to hold a reference to the currently loaded CoronaRuntimeEnvironment object via the “Loaded” event and release that reference via the “Terminating” event.  You’ll want to release the reference in the Terminating event so that the memory allocated by Corona can be freed when terminated… plus it’s your app’s clue that the Corona runtime is no longer running (ie:  “applicationExit” was called on it).

And in your case, instead of using a timer’s “Tick” event, you would tie it to a different .NET object’s event such as your TextBox’s events or perhaps your OK button’s “Clicked” event.

Hi Joshua, thank you so much for that! With that example I got it working exactly how I need it to!

Great!  Happy to help.  :slight_smile: