Arkadiy_Kolomiets
Topic Author
Posts: 9
Joined: 16 Jun 2024, 07:45

itemscontrol event trigger args equal to null

15 Sep 2024, 14:42

I have a collection of elements that I represent using an ItemsControl and each element is a button with which I want to call a certain function from view model by using MVVM pattern if one of the events occurs but the arguments come to the triggered function as null pointer


xaml
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Width="30" Height="30" Content="{Binding Index}">
                        <Button.RenderTransform>
                            <MultiBinding Converter="{StaticResource PositionConverter}">
                                <Binding Path="Index"/>
                                <Binding Path="Theta"/>
                                <Binding Path="DataContext.Radius" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                                <Binding Path="DataContext.CenterX" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                                <Binding Path="DataContext.CenterY" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                                <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
                                <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
                            </MultiBinding>
                        </Button.RenderTransform>

                        <!-- Event Handling for Point Buttons -->
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
                                <i:InvokeCommandAction Command="{Binding DataContext.PointMouseDownCommand, ElementName=RootUserControl}"
                                                       PassEventArgsToCommand="True"/>
                            </i:EventTrigger>
                            <i:EventTrigger EventName="PreviewMouseMove">
                                <i:InvokeCommandAction Command="{Binding DataContext.PointMouseMoveCommand, ElementName=RootUserControl}"
                                                       PassEventArgsToCommand="True"/>
                            </i:EventTrigger>
                            <i:EventTrigger EventName="PreviewMouseLeftButtonUp">
                                <i:InvokeCommandAction Command="{Binding DataContext.PointMouseUpCommand, ElementName=RootUserControl}"
                                                       PassEventArgsToCommand="True"/>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
ViewModel
    void CircleViewModel::onPointMouseDown(Noesis::BaseComponent* param) { // here is already null
        auto* event_args = Noesis::Boxing::Unbox<Noesis::EventArgs*>(param);
        auto* args = (Noesis::MouseButtonEventArgs*)(event_args);
        const auto type = param->GetClassType();

        isDraggingPoint = true;
        lastMousePosition = args->position;

        std::cout << "Mouse Down - Point at X: " << lastMousePosition.x << ", Y: " << lastMousePosition.y << std::endl;
    }
 
User avatar
sfernandez
Site Admin
Posts: 3363
Joined: 22 Dec 2011, 19:20

Re: itemscontrol event trigger args equal to null

17 Sep 2024, 20:46

What version of InvokeCommandAction source code are you using? In 3.2.4 we fixed a couple of issues related to that class when used inside templates:
- Fixed: InvokeCommandAction not cloning all members when used inside a template
- Fixed: InvokeCommandAction SetCommandParameter using wrong DP
Can you check that you're using the latest code of the interactivity classes?
 
Arkadiy_Kolomiets
Topic Author
Posts: 9
Joined: 16 Jun 2024, 07:45

Re: itemscontrol event trigger args equal to null

23 Sep 2024, 17:44

I've updated the version, this is the message from the terminal
[NOESIS/I] Noesis Init v3.2.4 (Linux on x86_64 Profile)
I'm running from the code via Noesis Launcher and version updating doesn't help in solving the problem, add more context for clarifying the encountering problem

i have item control with buttons, and every button is signed up to events via interactivity:
            <!-- Template for Point Buttons -->
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button x:Name="{Binding Index}" Width="30" Height="30" Content="{Binding Index}">
                        <Button.RenderTransform>
                            <MultiBinding Converter="{StaticResource PositionConverter}">
                                <Binding Path="Index"/>
                                <Binding Path="Theta"/>
                                <Binding Path="DataContext.Radius" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                                <Binding Path="DataContext.CenterX" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                                <Binding Path="DataContext.CenterY" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                                <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
                                <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
                            </MultiBinding>
                        </Button.RenderTransform>

                        <!-- Event Handling for Point Buttons -->
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
                                <i:InvokeCommandAction Command="{Binding DataContext.PointMouseDownCommand, ElementName=RootUserControl}"
                                                       PassEventArgsToCommand="True"/>
                            </i:EventTrigger>
                            <i:EventTrigger EventName="PreviewMouseMove">
                                <i:InvokeCommandAction Command="{Binding DataContext.PointMouseMoveCommand, ElementName=RootUserControl}"
                                                       PassEventArgsToCommand="True"/>
                            </i:EventTrigger>
                            <i:EventTrigger EventName="PreviewMouseLeftButtonUp">
                                <i:InvokeCommandAction Command="{Binding DataContext.PointMouseUpCommand, ElementName=RootUserControl}"
                                                       PassEventArgsToCommand="True"/>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
The related ViewModel binds the event actions by DelegateCommand
#include <NsApp/DelegateCommand.h>
...
        pointMouseDownCommand.SetExecuteFunc(Noesis::MakeDelegate(this, &CircleViewModel::onPointMouseDown));
        pointMouseMoveCommand.SetExecuteFunc(Noesis::MakeDelegate(this, &CircleViewModel::onPointMouseMove));
        pointMouseUpCommand.SetExecuteFunc(Noesis::MakeDelegate(this, &CircleViewModel::onPointMouseUp));
        
...
    void CircleViewModel::onPointMouseDown(Noesis::BaseComponent* param) { // param is nullptr
    }

And i have the same code outside the ItemsControl that works properly
        <Button x:Name="CenterButton" Width="40" Height="40" Content="C">
            <Button.RenderTransform>
                <MultiBinding Converter="{StaticResource CenterPositionConverter}">
                    <Binding Path="CenterX"/> <!-- New X position from ViewModel -->
                    <Binding Path="CenterY"/> <!-- New Y position from ViewModel -->
                    <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/> <!-- Button width -->
                    <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/> <!-- Button height -->
                </MultiBinding>
            </Button.RenderTransform>

            <!-- Event Handling for Center Button -->
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
                    <i:InvokeCommandAction Command="{Binding DataContext.MouseDownCenterCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" PassEventArgsToCommand="True"/>
                </i:EventTrigger>
                <i:EventTrigger EventName="PreviewMouseMove">
                    <i:InvokeCommandAction Command="{Binding DataContext.MouseMoveCenterCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" PassEventArgsToCommand="True"/>
                </i:EventTrigger>
                <i:EventTrigger EventName="PreviewMouseLeftButtonUp">
                    <i:InvokeCommandAction Command="{Binding DataContext.MouseUpCenterCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" PassEventArgsToCommand="True"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
 
User avatar
sfernandez
Site Admin
Posts: 3363
Joined: 22 Dec 2011, 19:20

Re: itemscontrol event trigger args equal to null

25 Sep 2024, 13:29

Could you please verify that the source code for InvokeCommandAction.cpp includes this method:
void InvokeCommandAction::CloneCommonCore(const Noesis::Freezable* source)
{
    ParentClass::CloneCommonCore(source);

    InvokeCommandAction* action = (InvokeCommandAction*)source;
    mCommandName = action->mCommandName;
    mPassEventArgsToCommand = action->mPassEventArgsToCommand;
}
And that you are compiling the interactivity classes (or NoesisApp.dll if you use our application framework).

Because the problem with args not being passed when used inside templates is already fixed.

Who is online

Users browsing this forum: No registered users and 10 guests