Using c++ to show in blueprint ListView -> Entry Widget Class

So I have no idea what I am doing, I’ve tried to figure this out looking at various online articles. The code I have so far is:

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/TextBlock.h"
#include "BuildingListItem.generated.h"

UCLASS(Blueprintable, BlueprintType)
class GAMEUI_API UBuildingListItem : public UUserWidget
{
    GENERATED_BODY()
public:
    UBuildingListItem(const FObjectInitializer& ObjectInitializer) :
        Super(ObjectInitializer)
    {}

    void NativeConstruct() override
    {
        Super::NativeConstruct();
    }

    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mType;
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mCount;
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mHeight;
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mConstructionFactor;
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mBasement;
};

I’ve tried adding the UBuildingListItem in code. However the data, is lost.

void Location::GetBuildingSummary(UListView* aList)
{
    aList->ClearListItems();
    TArray<BuildingSummary> buildings;
    // code to generate the buildings list goes here

    for (auto it = buildings.begin(); it != buildings.end(); ++it)
    {
        UBuildingListItem* row = CreateWidget<UBuildingListItem>(aList);
        row->mBasement = NewObject<UTextBlock>();
        row->mConstructionFactor = NewObject<UTextBlock>();
        row->mCount = NewObject<UTextBlock>();
        row->mHeight = NewObject<UTextBlock>();
        row->mType = NewObject<UTextBlock>();
        row->mBasement->SetText(FText::FromString((*it).mBuilding->GetBasement() ? "True" : "False"));
        row->mConstructionFactor->SetText(FText::FromString(FString::Printf(TEXT("%d"), (*it).mBuilding->GetConstructionFactor())));
        row->mCount->SetText(FText::FromString(FString::Printf(TEXT("%d"), (*it).mCount)));
        row->mHeight->SetText(FText::FromString(FString::Printf(TEXT("%d"), (*it).mBuilding->GetHeight())));
        switch ((*it).mBuilding->GetType())
        {
        case BuildingType::Residential:
            row->mType->SetText(FText::FromString("Residential"));
            break;
        case BuildingType::Commercial:
            row->mType->SetText(FText::FromString("Commercial"));
            break;
        case BuildingType::Manufacturing:
            row->mType->SetText(FText::FromString("Manufacturing"));
            break;
        case BuildingType::Research:
            row->mType->SetText(FText::FromString("Research"));
            break;
        case BuildingType::ResearchComplex:
            row->mType->SetText(FText::FromString("Research Complex"));
            break;
        default:
            row->mType->SetText(FText::FromString("Unknown"));
        }

        aList->AddItem(row);
    }
}

All the above data is lost, as per the below image.
image
Any ideas on how to fix this code?

While I don’t know c++, it looks like you create a widget, manipulate some data and then add that widget to the listview.
That means that the widget you created is an item of the listview.
And that the displayed widget that the listview generates for the item, is unchanged resulting in the default text blocks texts.

The entrywidget class has events called when it is generated, and that is where you pull the data from the item to update your text blocks.
As such, the item does not have to be a widget and having it a widget might become a bit confusing to work with.

Getting closer (I think), the new User Widget.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Blueprint/IUserObjectListEntry.h"
#include "Components/TextBlock.h"
#include "BuildingListItem.generated.h"

UCLASS(Blueprintable, BlueprintType)
class GAMEUI_API UBuildingListItem : public UUserWidget, public IUserObjectListEntry
{
    GENERATED_BODY()
public:
    UBuildingListItem(const FObjectInitializer& ObjectInitializer) :
        Super(ObjectInitializer)
    {}

    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mType;
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mCount;
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mHeight;
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mConstructionFactor;
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BuildingData", meta = (BindWidget)) UTextBlock* mBasement;

    virtual bool IsListItemSelectable() const { return false; }
protected:
    virtual void NativeOnListItemObjectSet(UObject* ListItemObject) override;
};

The item class

#pragma once

#include "CoreMinimal.h"
#include "BuildingSummaryItem.generated.h"

UCLASS()
class GAMEUI_API UBuildingSummaryItem : public UObject
{
	GENERATED_BODY()
public:

    FString mType;
    FString mCount;
    FString mHeight;
    FString mConstructionFactor;
    FString mBasement;
};

The blue print for it:

However the List View doesn’t like the new UBuildingListItem. I can add it as the Entry Widget Class. I seem to be missing something with the implementation of the IUserObjectListEntry.

image

Any more thoughts would be great.