Properties edited in PostEditChangeProperty do not update details panel

We put some data validation in PostEditChangeProperty which fixes up a property when another property is modified. Basically, property B’s validity is dependent on property A.

When property B is modified in PostEditChangeProperty, however, it does not update the actual display in the details window. I assume that there might be some kind of dirty flag needs to be set, or maybe even invalidate the entire layout, but I can’t figure out how to do so.

These properties happen to be GameplayTagContainers.

I’m having the same problem.
If PostEditChangeProperty is triggered because of a change on value A, it seems like A is the only value I can modify. (I want to modify B)

I’ve searched quite a bit online, but I haven’t found any answer.

Hello guys,

Any luck doing that. I am trying to hide Property A because Property B is changed. Have any ideas how can I accomplish that.

I am new to unreal, so please pardon me If I am asking something very obvious.

Thanks

Even code in unreal has this problem. The UI Sequencer → Render Movie Settings → Burn in Options → Settings has this same issue when toggling between burn in classes in 4.21

I’ve been able to work around this by using a timer inside PostEditChangeProperty to update my uproperty. In my case, I null out the property in PostEditChangeProperty, then set a new value in the callback. It would be nice if there was some way to do this without a timer, as it feels like a hack.

Rough Example:

void UMyClass::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
    FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None;

    if (PropertyName == GET_MEMBER_NAME_CHECKED(UMyClass, MonitoredProperty))
    {
        if (OtherProperty != nullptr)
        {
            OtherProperty->Rename(*MakeUniqueObjectName(this, USettingsObject::StaticClass(), "Settings_EXPIRED").ToString());
            OtherProperty->MarkPendingKill();
            OtherProperty = nullptr;
        }
        if (GEditor)
        {
            FTimerHandle TimerHandle;
            GEditor->GetTimerManager()->SetTimer(
                TimerHandle,
                this,
                &UMyClass::UpdateSettings,
                0.01f,
                false);
        }
    }
    Super::PostEditChangeProperty(PropertyChangedEvent);
}

void UMyClass::UpdateSettings()
{
    OtherProperty = NewObject<USettingsObject>();
}

I had this problem, and the solution for me was to call through to Super::PostEditChangeProperty(PropertyChangedEvent) after making my change to the other value instead of doing that before making my change.

2 Likes

I know this was posted a while ago, but in case anyone else ends up here, I just managed to get this working by overloading these three methods, and performing the update before calling into Super:

#if WITH_EDITOR
	virtual void PostEditChangeProperty(struct FPropertyChangedEvent& InChangeEvent) override;
	virtual void PostCDOCompiled(const FPostCDOCompiledContext& Context) override;
	virtual void PostTransacted(const FTransactionObjectEvent& TransactionEvent) override;
#endif // WITH_EDITOR

EDIT: Further Follow up:

Some more testing, and it appears to work with just overloading this method:

virtual void PostEditChangeProperty(struct FPropertyChangedEvent& InChangeEvent) override;

However, I ran into issues, where in my case I was assigning a dynamic material instance to the Class Default Object’s static mesh whenever I updated the Blueprint Default. This would cause a Save error to the instances in the editor, (something along the lines of referencing an external private property instance).

I added the following flag check to make sure I wasn’t doing it on the CDO. (Checking owner as this was a actor component).

if (GetOwner() && GetOwner()->HasAnyFlags(RF_ClassDefaultObject)) return;

That seems to be stable so far… :crossed_fingers:

1 Like