Page 1 of 2

"Insufficient buffer size" while making delegate

Posted: 18 Dec 2024, 00:47
by Mikhail Yanakayev
Hello!
I'm trying to create delegate and attach it to ScrollChanged event in my ScrollViewer. It works OK if I doing it with lambda, something like this:
myScroll->StatusChanged() += [](Noesis::BaseObject* sender, const Noesis::ScrollChangedEventArgs&) {dosomething();};
But if I want to make it with delegate
Noesis::ScrollChangedEventHandler delegate = Noesis::MakeDelegate(this, &MyClass::OnScrollChanged);
myScroll->ScrollChanged() += delegate;
then get static assert "Insufficient buffer size" in MakeDelegate function.

How it can be solved?
I'm using Noesis 3.2.6

Thank you!

Re: "Insufficient buffer size" while making delegate

Posted: 18 Dec 2024, 02:11
by Mikhail Yanakayev
Also, to not create new topic:
I want to scroll content a bit after ScrollChanged delegate will called. If I call ScrollToVerticalOffset inside this delegate, it called recursively. So I call
myScroll->StatusChanged() -= delegate;
right before ScrollToVerticalOffset to not call this delegate on my scrolling. But seems it doesn't work since it still called recursively while ScrollViewer reached bottom elements.
It seems that delegate removing doesn't work properly or I'm doing something wrong.
Could you give a clue?

Thanks!

Re: "Insufficient buffer size" while making delegate

Posted: 18 Dec 2024, 11:51
by jsantos
I am a bit confused by your message because you mention the ScrollChanged event, but in your code, you appear to be mixing StatusChanged and ScrollChanged.

That said, there is a limitation (#1141) in our lambda implementation: to avoid extra heap allocations, there is a limit to the size of the context captured by a lambda.

However, you shouldn’t encounter any errors when using non-lambda delegates. Could you please share the exact code that produces the error, along with the specific compiler error message?

Additionally, note that lambda delegates cannot be removed from event handlers (#1081). Therefore, although it may be more tedious, we recommend using standard member delegates

Re: "Insufficient buffer size" while making delegate

Posted: 18 Dec 2024, 18:41
by Mikhail Yanakayev
Sorry, ofcourse I meant ScrollChanged and confused events when wrote code by memory )

Here's parts of code which related to topic:
bool MYNAMESPACE::MyClass::ScrollToExactPosition(int rowToScroll, int elementToOpen)
{
	Noesis::VirtualizingStackPanel* panel = m_scroll->GetTemplateChild<Noesis::VirtualizingStackPanel>("Virtualizer");
	if (panel)
	{
		Noesis::ItemsControl* owner = Noesis::ItemsControl::GetItemsOwner(panel);
		if (!owner || owner->GetItems()->Count() < rowToScroll)
			return false;
		panel->BringIndexIntoView(rowToScroll);
		
		if (m_itemsControl && m_itemsControl->IsLoaded())
		{
			if (m_itemsControl->GetItemContainerGenerator()->GetStatus() == Noesis::GeneratorStatus_ContainersGenerated)
			{
				Noesis::ItemCollection* itemCollection = m_itemsControl->GetItems();
				if (itemCollection)
				{
					Noesis::ContentPresenter* presenter = Noesis::DynamicCast<Noesis::ContentPresenter*>(m_itemsControl->GetItemContainerGenerator()-		>ContainerFromIndex(rowToScroll));
			if (presenter && presenter->IsLoaded())
			{
				Noesis::UniformGrid* uniformGrid = Noesis::DynamicCast<Noesis::UniformGrid*>(Noesis::VisualTreeHelper::GetChild(Noesis::DynamicCast<Noesis::Visual*>(presenter), 0));
				Noesis::ContentPresenter* elementContent = Noesis::DynamicCast<Noesis::ContentPresenter*>(Noesis::VisualTreeHelper::GetChild(Noesis::DynamicCast<Noesis::Visual*>(uniformGrid), elementToOpen));
				Noesis::FrameworkElement* animatedElement = Noesis::DynamicCast<Noesis::FrameworkElement*>(elementContent->GetTemplateChild("MainGrid"));

				m_scroll->ScrollChanged() += Noesis::MakeDelegate(this, &MyClass::OnScrollChanged); // ==> here we got static assert
				if (animatedElement)
				{
					Noesis::VisualStateManager::GoToElementState(animatedElement, Noesis::Symbol("Opening"), false);
				}
			}
		}
		return true;
	}
	return false;
}

void MYNAMESPACE::MyClass::OnScrollChanged(Noesis::BaseObject* sender, const Noesis::ScrollChangedEventArgs&)
{
	Noesis::ScrollViewer* scroll = Noesis::DynamicCast<Noesis::ScrollViewer*>(sender);
	printf("%f\n", scroll->GetVerticalOffset());
	scroll->ScrollChanged() -= Noesis::MakeDelegate(this, &MyClass::OnScrollChanged);
	scroll->ScrollToVerticalOffset(scroll->GetVerticalOffset() + scroll->GetActualHeight() * 0.5f);
}

Re: "Insufficient buffer size" while making delegate

Posted: 18 Dec 2024, 19:41
by jsantos
Thanks, can I also have a look at the layout of MyClass (at least see the parent classes, could it be that you are using multiple virtual base classes?)

Re: "Insufficient buffer size" while making delegate

Posted: 18 Dec 2024, 20:49
by Mikhail Yanakayev
This class inherits this VM_Base class that inherits NoesisApp::NotifyPropertyChangedBase. Also, we're used already MakeDelegate inside same class and everything worked like a charm. This call is only problem place actually
	class VM_Base : public NoesisApp::NotifyPropertyChangedBase
	{
	public:
		VM_Base() {}
	};
UPD: this MakeDelegate don't lead to any issues if don't assigned to any delegate variable and just called just like that
MakeDelegate(this, MyClass::OnScrollChanged)
Maybe because of optimizations, but optimization is turned off in my config.

UPD2: It worked when I made just function, not member of class, and assigned it to ScrollChanged(). So looks like it's really class structure problem. What in theory it can be?

Re: "Insufficient buffer size" while making delegate

Posted: 20 Dec 2024, 10:11
by jsantos
I am not able to reproduce this in a minimal sample like this one:
#include <NsApp/NotifyPropertyChangedBase.h>
#include <NsCore/Delegate.h>

class VM_Base : public NoesisApp::NotifyPropertyChangedBase
{
public:
    VM_Base() {}
};

class MyClass : public VM_Base
{
public:
    MyClass()
    {
        Delegate<void()> func;
        func += MakeDelegate(this, &MyClass::OnScrollChanged);
    }

    void OnScrollChanged()
    {
    }
};
This works fine, could you please indicate what changes are needed to reproduce your error? Is this on Visual Visual Studio?

Re: "Insufficient buffer size" while making delegate

Posted: 26 Dec 2024, 18:26
by Mikhail Yanakayev
Sorry for a long answer.
I've tried this, and got same error:
	class VM_Base : public NoesisApp::NotifyPropertyChangedBase
	{
	public:
		VM_Base() {}
	};

	class MyClass : public VM_Base
	{
		MyClass()
		{
			viewer->ScrollChanged() += Noesis::MakeDelegate(this, &MyClass::OnScrollChanged);
		}

		void OnScrollChanged() {}

	private:
		Noesis::ScrollViewer* viewer;
	};

Re: "Insufficient buffer size" while making delegate

Posted: 27 Dec 2024, 11:17
by sfernandez
The problem with your last code is that the method signature does not match the event handler. This should work:
void OnScrollChanged(Noesis::BaseComponent* sender, const Noesis::ScrollChangedEventArgs& e) {}

Re: "Insufficient buffer size" while making delegate

Posted: 27 Dec 2024, 12:24
by jsantos
The error we are giving is not very correct though... let me see if we can do better.