Using the UMG MVVM system, is there anyway to bind yourself directly into the code, without going with the UI ?

Hello,

I’ve been fiddling with UMG and the MVVM plugin, which is quite nice !
I’m trying to replicate 2 things

  • First, being able to create, from C++, a variable that is set as Notify, so on the BluePrint or code side, I could broadcast the value. Whatever I’ve tried to do (Setting the FieldNotify parameter for exemple), I’m never able to “broadcast” my value, wheares on Blueprint, I can do it easely. Is that the normal behavior ?

  • Secondly, I would like directly from the code to listen to that value. Let’s say I don’t want to listen it from the UI, but from an other system (Like a statistics system). I’m trying my best, but I don’t see how I can “bind” myself to that broadcasted value ?

Thank you if you have any answer !

  1. How you are broadcasting a value in Blueprint? I think your confusion is that FieldNotify is for UI only, in C++ we use DELEGATES or Getter functions, for example.

  2. In C++ you can use DELEGATES:

MVVM.h

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyIntVariable, int32, Value);

public:
	UPROPERTY(BlueprintAssignable)
	FMyIntVariable OnVariableChange;

MVVM.cpp

{
	// when variable changes.
	OnVariableChange.Broadcast(Value);
}

Statistics.h

void OnMyIntChange(const int32 Value);

Statistics.cpp

MyMVVM->OnVariableChange.AddUniqueDynamic(this, &ThisClass::OnMyIntChange);

void AStatistics::OnMyIntChange(const int32 Value)
{
	// value changed.
}

You can bind OnVariableChange in Blueprint too because we are using BlueprintAssignable.

You absolutely can bind a function to a field notify in code. The Field Notify system, under the hood, is basically a delegate reflection system tied to specific variables and their signaling that there has been a change. You can actually create a VM that is never used by the UI that drives other code if you really wanted to (though there are better ways than this system to do that). If you have some overlap between code and the UI, I would still say that unless the overlap is UI congruent, not UI adjacent, you should not be using MVVM to reflect those changes in the rest of your code base.

That all said,

ViewModelBasePtr->AddFieldValueChangedDelegate(ViewModelType::FFieldNotificationClassDescriptor::MemberName, INotifyFieldValueChanged::FFieldValueChangedDelegate::CreateUObject(this, ScopedFunctionName));

This of course can be adapted to any of the delegate classics, like Weak Lambda, UObject, etc. Unlike normal delegates, there is no automatic release of the binding so you need to call RemoveAllFieldValueChangedDelegates on the VM or other similar remove functions per property on the VM.