Unreal Engine - Using list view widget in Slate

Posted on Apr 12, 2023

SListView widget is one of the very few widgets that allow for dynamic content addition. Because of that it requires a very specific setup which is not very well documented thus my need for documenting it here.

Setup

This is snippet presenting how to define a list view in Slate:

SAssignNew(MyListView, SListView<TSharedPtr<FMyDataStruct>>)
    .ListItemsSource(&MyDataList)
    .SelectionMode(ESelectionMode::Single)
    .OnGenerateRow_Lambda([](
        TSharedPtr<FMyDataStruct> MyData, const TSharedRef<STableViewBase>& OwnerTable)
    {
        return SNew(SMyTableRow, OwnerTable)
            .InMyData(MyData);
    })
    .OnSelectionChanged_Lambda([this](
        TSharedPtr<FMyDataStruct> NewSelectionData, ESelectInfo::Type SelectInfo)
    {
        UE_LOG(LogTemp, Log, TEXT(""));
    })

This is declaration of the list view in a corresponding header file:

TSharedPtr<SListView<TSharedPtr<FMyDataStruct>>> MyListView;

This is declaration of the FMyDataStruct used as parameter for the list view:

struct FMyDataStruct
{
	FText RowName;
    int32 MyInt;
    float MyFloat;
};

This is declaration of the row widget:

class SMyTableRow : public STableRow<TSharedPtr<FMyDataStruct>>
{
public:
	SLATE_BEGIN_ARGS(SMyTableRow)
		: _InMyData(nullptr)
	{}
	SLATE_ARGUMENT(TSharedPtr<FMyDataStruct>, InMyData)
	SLATE_END_ARGS()

	void Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTableView);
private:
	TSharedPtr<FMyDataStruct> MyData;
};

Finally an array that is passed by reference to the list view and is used to generate new rows:

TArray<TSharedPtr<FMyDataStruct>> MyDataList;

For delegates, there are really only two important ones:

.OnGenerateRow_Lambda([](
    TSharedPtr<FMyDataStruct> MyData, const TSharedRef<STableViewBase>& OwnerTable)
{
    return SNew(SMyTableRow, OwnerTable)
        .InMyData(MyData);
})

which is called whenever new items are added to the MyDataList. This function should return a widget that will act as a new row in the list view.

Second one is

.OnSelectionChanged_Lambda([this](
    TSharedPtr<FMyDataStruct> NewSelectionData, ESelectInfo::Type SelectInfo)
{
    UE_LOG(LogTemp, Log, TEXT(""));
})

which is called whenever the user selects a new row. Use this to update data for your system or tool.

Usage

As mentioned in the setup, the usage is very simple and straightforward. Instead manually generating row and adding it to the list view widget all we need to do in order to generate new row (or delete existing one) is to add a new item to the MyDataList array. Because this array is passed by reference to the list view it will listen for any change in it and update itself appropriately to the situation.