User avatar
SL_Rico
Topic Author
Posts: 12
Joined: 03 Jul 2021, 08:18

Control Events not being invoked

04 Dec 2021, 19:21

Good evening!

I tried several ways to listen for KeyDown events for a TextBox control, unfortunately without success.
The case is pretty simple: I have a UserControl containing a Grid which contains a TextBox. I want to listen to the KeyDown event. Entering text in the TextBox by typing works as expected, but the KeyDown event is never called - independently by the way of registering the event (by XAML or code behind).

Am I missing something?

Thank you in advance :)
 
User avatar
SL_Rico
Topic Author
Posts: 12
Joined: 03 Jul 2021, 08:18

Update: Control Events not being invoked

06 Dec 2021, 10:28

Update: It seems that no events are registered at all. I additionally created a Button today and added a Click-event handler (first by XAML, then in code behind only) and it does not work at all.

XAML
<UserControl x:Class="SL.RuadhSagas.UI.Misc.DevConsoleUI"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <UserControl.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisibility" />
    </UserControl.Resources>

    <Grid VerticalAlignment="Top"
          MinWidth="720"
          MinHeight="256"
          HorizontalAlignment="Center"
          Visibility="{Binding Path=PanelVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibility}}"
          Background="#CC000000">

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="45" />
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0"
                    Orientation="Vertical"
                    Margin="5">
            <TextBlock Text="Development Console v1"
                       Foreground="White" />
        </StackPanel>

        <Grid Grid.Row="1"
              Margin="5">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="100" />
            </Grid.ColumnDefinitions>

            <TextBox Grid.Column="0"
                     Name="CommandInput"
                     Foreground="White" />

            <Button Grid.Column="1"
                    Name="CommandExecute"
                    Content="Run" />
        </Grid>
    </Grid>
</UserControl>
C#
#if UNITY_5_3_OR_NEWER
#define NOESIS
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
using Noesis;
using UnityEngine;
#else
using System;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
#endif

namespace SL.RuadhSagas.UI.Misc
{
    public partial class DevConsoleUI : UserControl, INotifyPropertyChanged
    {
        private bool _panelVisible;

        private TextBox cmdInput;
        private Button cmdExecute;

        public bool PanelVisible
        {
            get => _panelVisible;
            set
            {
                if (value == _panelVisible)
                    return;

                _panelVisible = value;
                OnPropertyChanged();
            }
        }

        public DevConsoleUI()
        {
            InitializeComponent();

            DataContext = this;
            cmdInput = FindName("CommandInput") as TextBox;
            cmdExecute = FindName("CommandExecute") as Button;
        }

        private void CommandInput_OnKeyDown(object sender, KeyEventArgs e)
        {
            var cIn = sender as TextBox;

            if (e.Key != Key.Enter && e.Key != Key.Return)
                return;

            var cmdStr = cIn.Text;
            cIn.Clear();

            Debug.Log($"Command entered: {cmdStr}");
            
            e.Handled = true;
        }
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            Debug.Log("Test123");
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

#if NOESIS
        private void InitializeComponent()
        {
            NoesisUnity.LoadComponent(this);
        }
#endif
    }
}
It's pretty simple. The PanelVisible property is working, the Binding works too.
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Control Events not being invoked

06 Dec 2021, 12:43

Hi, you are not hooking to those events anywhere in the code. You should do something like this:
public DevConsoleUI()
{
  InitializeComponent();

  DataContext = this;
  
  cmdInput = FindName("CommandInput") as TextBox;
  cmdInput.PreviewKeyDown += CommandInput_OnKeyDown;
  
  cmdExecute = FindName("CommandExecute") as Button;
  cmdExecute.Click += ButtonBase_OnClick;
}
Also note that TextBox handles KeyDown events (for some keys), so you may want to hook to the PreviewKeyDown in case you want to capture the keys before the TextBox does it.
 
User avatar
SL_Rico
Topic Author
Posts: 12
Joined: 03 Jul 2021, 08:18

Re: Control Events not being invoked

07 Dec 2021, 03:20

Hi there and thank you for you answer!

This is really weird. I previously had the events registered the exact same way you posted, but it didn't worked at all - while other views in the same scene worked perfectly fine! Now - after several restarts of the engine - it works as intended. In the code I posted above the event registration is probably missing because I decided to create this topic after several attempts to get it to work, so I'm sorry for the confusion at this point - the code for registering events were definitely there, I just forgot to place them back in the code before posting it here.

Anyways it seems that sometimes events are not getting registered. I'm currently using Unity 2021.2.5f1 and working with Noesis for around six month now so actually registering events shouldn't be a topic anymore :D

But for now: Thanks again for your support, as always!
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Control Events not being invoked

07 Dec 2021, 16:48

Anyways it seems that sometimes events are not getting registered.
Do you recall if that happened when hot-reloading a xaml while you had your game playing?
 
User avatar
SL_Rico
Topic Author
Posts: 12
Joined: 03 Jul 2021, 08:18

Re: Control Events not being invoked

08 Dec 2021, 19:28

No, only at initialization time. Restarting the engine solved the problem to it's maybe not an issue with Noesis but with Unity itself. I'll let you know if I find a way to reproduce the issue :)
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Control Events not being invoked

09 Dec 2021, 10:23

Thanks, it would help if you find a way to reproduce it because I don't think it could be a Unity problem.
 
User avatar
SL_Rico
Topic Author
Posts: 12
Joined: 03 Jul 2021, 08:18

Re: Control Events not being invoked

22 Dec 2021, 13:07

Hey there again!

Coming back to the initial question: Is it possible to use the event attributes in XAML to register events at all?
I'm working with Unity and the only way to get events to work is to manually register them inside the backend code.

Here's a simple, not working example:
<UserControl x:Class="SL.RuadhSagas.UI.Misc.PartyInventory"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:system="clr-namespace:System;assembly=mscorlib"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:viewModel="clr-namespace:Ruadh_Sagas.Assets.Code.XAML.ViewModel"
             xmlns:components="clr-namespace:SL.RuadhSagas.UI.Components"
             mc:Ignorable="d">
    <Viewbox>
        <Button Content="Click me!" Click="ClickHandler" />
    </Viewbox>
</UserControl>
#if UNITY_5_3_OR_NEWER
#define NOESIS
using System;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using Noesis;

#else
using System;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
#endif

namespace SL.RuadhSagas.UI.Misc
{
    public partial class PartyInventory : UserControl
    {

        public PartyInventory()
        {
            InitializeComponent();
        }

        private void ClickHandler(object sender, RoutedEventArgs e)
        {
            UnityEngine.Debug.Log("Clicked!");
        }

#if NOESIS
        private void InitializeComponent()
        {
            NoesisUnity.LoadComponent(this);
        }
#endif
    }
}
Is there no way to register events by XAML attributes without manually registering them using FindName("elementName") and the respective event registration?

Edit: Almost forget ... the actual issue is, that Noesis throws an error complaining that there is no definition for "ClickHandler". Even though the handler is a public method.

Kind regards
Rico
 
User avatar
SL_Rico
Topic Author
Posts: 12
Joined: 03 Jul 2021, 08:18

Re: Control Events not being invoked

22 Dec 2021, 14:11

Solved this!

I missed an important override as described in https://www.noesisengine.com/docs/Gui.C ... bscription
So adding the following method override to the code behind class fixes the issue:
protected override bool ConnectEvent(object source, string eventName, string handlerName)
{
    if (eventName == "Click" && handlerName == nameof(ClickHandler))
    {
        ((Button)source).Click+= ClickHandler;
        return true;
    }

    return false;
}
I'm sorry for the inconvenience.

Kind regards
Rico
 
User avatar
jsantos
Site Admin
Posts: 3906
Joined: 20 Jan 2012, 17:18
Contact:

Re: Control Events not being invoked

22 Dec 2021, 14:22

Yes, that's the solution. We have plans to auto-generate this (#1790).

A much better alternative is avoiding events in XAML and just use MVVM. Just have a look at our Buttons sample in Unity.

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 5 guests