NoesisGUI

Events in NoesisGUI

NoesisGUI is an event driven framework where all controls expose a range of events that you may subscribe to. You can subscribe to this events, which means that your application will be notified when they occur and you may react to that.

There are many types of events, but some of the most commonly used are there to respond to the user's interaction. On most controls you will find events like KeyDown, KeyUp, MouseDown, MouseUp, TouchDown, TouchUp. For example, in the events section of the UIElement documentation you can find a list of all the events exposed by that class. The same for the rest of classes.

NOTE

Find more information about events in the following document.

Two different ways can be used to subscribe to events in NoesisGUI: with and without code-behind.

Direct subscription

The easiest way to subscribe to an event is directly adding a callback to it by using a delegate. The object is reached using FindName, so you need to use the x:Name keyword to set the name of the desired instance. For example, given the following XAML:

<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Button x:Name="button" Width="100" VerticalAlignment="Center" Content="Click me"/>

</Grid>

C++

Ptr<Grid> root = GUI::LoadXaml<Grid>("Grid.xaml");
Button* button = root->FindName<Button>("button");
button->Click() += [](BaseComponent* sender, const RoutedEventArgs& args)
{
    printf("Button was clicked");
};

C#

Grid root = (Grid)GUI.LoadXaml("Grid.xaml");
Button button = (Button)root.FindName("button");
button.Click += (object sender, RoutedEventArgs args) =>
{
    System.Console.WriteLine("Button was clicked");
};

Code-behind subscription

The alternative to direct subscription is using code-behind and connecting the event in the XAML by writing method names. These method names need to be defined in code-behind using the correct event signature. For example:

<Grid x:Class="MyGrid"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Button Width="100" VerticalAlignment="Center" Content="Click me" Click="OnButtonClick"/>
</Grid>

NOTE

Read the Extending Noesis tutorial to know more about implementing code-behind classes

FrameworkElement exposes a virtual function Connect that is invoked for each hooked event when the XAML is loaded. You need to reimplement that function accordingly.

C++

class MyGrid: public Grid
{
public:
    MyGrid()
    {
        InitializeComponent();
    }

private:
    void InitializeComponent()
    {
        GUI::LoadComponent(this, "Grid.xaml");
    }

    void Connect(BaseComponent* source, const NsChar* eventName, const NsChar* handlerName) override
    {
        #define CONNECT_EVENT_HANDLER(sourceType, event, handler) \
            if (String::Compare(eventName, #event) == 0 && String::Compare(handlerName, #handler) == 0) \
            { \
                ((sourceType*)source)->event() += MakeDelegate(this, &MyGrid::handler); \
                return; \
            }

        CONNECT_EVENT_HANDLER(Button, Click, OnButtonClick);
    }

    void OnButtonClick(BaseComponent* sender, const RoutedEventArgs& args)
    {
        printf("Button was clicked");
    }

    NS_IMPLEMENT_INLINE_REFLECTION(MyGrid, Grid)
    {
        NsMeta<TypeId>("MyGrid");
    }
};

C#

public class MyGrid: Grid
{
    public MyGrid()
    {
        InitializeComponent();
    }

    private void InitializeComponent()
    {
        GUI.LoadComponent(this, "Grid.xaml");
    }

    protected override void Connect(object source, string eventName, string handlerName)
    {
        if (eventName == "Click" && handlerName == "OnButtonClick")
        {
            ((Button)source).Click += this.OnButtonClick;
        }
    }

    private void OnButtonClick(object sender, RoutedEventArgs args)
    {
        System.Console.WriteLine("Button was clicked");
    }
}

Note that sometimes using FindName is not a valid option and this is the only way to connect to events. For example when using a DataTemplate the named elements in the visual tree cannot be accessed using FindName.

<Grid x:Class="MyGrid"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid.Resources>
        <DataTemplate x:Key="BookItemTemplate">
            <StackPanel Orientation="Horizontal">
                <Button Content="+" Click="OnButtonClick" />
                <TextBlock Text="{Binding Title}"/>
            </StackPanel>
        </DataTemplate>
    </Grid.Resources>
    <ListBox ItemsSource="{Binding Books}" ItemTemplate="{StaticResource BookItemTemplate}"/>
</Grid>
© 2017 Noesis Technologies