Slate ListView RequestListRefresh

Is there something special that needs to be done to use RequestListRefresh on a ListView so that the widget actually refreshes? It works intermittently for me.

I have two ListViews, a master with an OnSelectionChanged delegate, where I change the array of items that should be displayed on the slave ListView (the ListItemsSource) and call RequestListRefresh. The array is correctly filtered, but visually the slave ListView only refreshes about half the time when I change the selection.

Is it a timing issue?

EDIT: If I slightly resize the window that the ListViews are in, it refreshes. Is there a way to force the refresh?

you should call RequestListRefresh on “slave” list. If you’re doing it already, it would be good to see your code in OnSelectionChanged and Lists creation so we can have better understanding of your setup.

Here you go. Actually, if you see messy code, please feel free to critique.

The GenerateShipEngineList function does change the list properly on each selection change (seen in the debug output), it is just the widget that does not visually update half the time.

EngineListView is the slave list, which is filtered according to propulsion type.




//GameDialog.h

//declarations
private:
TArray< TSharedPtr< FShipPropulsionData > > ShipPropulsionItems;
TArray< TSharedPtr< FShipEngineData > > ShipEngineItems;
TSharedPtr<SListView< TSharedPtr<FShipPropulsionData> >> EngineListView;


//GameDialog.cpp
// on selection changed function
void GameDialog::PropulsionEntrySelectionChanged(TSharedPtr<FShipPropulsionData> InItem, ESelectInfo::Type SelectInfo) {
	UE_LOG(LogClass, Log, TEXT("GameDialog::PropulsionEntrySelectionChanged %s"),*InItem->PropulsionID);
	GenerateShipEngineList(InItem->PropulsionID);
	SelectedPropulsionItem = InItem;
	EngineListView->RequestListRefresh();
}

//list update function
void GameDialog::GenerateShipEngineList(FString type) {
	UE_LOG(LogClass, Log, TEXT("GameDialog::GenerateShipEngineList %s"),*type);

	if (EngineListView.IsValid() && EngineListView->IsPendingRefresh()) {
		UE_LOG(LogClass, Log, TEXT("GameDialog::GenerateShipEngineList %s PENDING"),*type);
		return;
	}

	ShipEngineItems.Empty();
	TWeakObjectPtr<UDataTable> dataTable = GameShipData::Get()->ShipEngineDataTable;
	if (dataTable.IsValid()) {
		TArray<FName> rowNames;
		dataTable->RowMap.GetKeys(rowNames);
		for(const auto& row : rowNames) {
			FShipEngineData* ptr = dataTable.Get()->FindRow<FShipEngineData>(row,row.ToString());
			if (ptr != nullptr && ptr->PropulsionID == type) {
				UE_LOG(LogClass, Log, TEXT("GameDialog::GenerateShipEngineList %s %s"),*type,*ptr->LongName);
				TSharedPtr<FShipEngineData> spd = MakeShareable(new FShipEngineData(*ptr));
				ShipEngineItems.Add(spd);
			}
		}
	}
}

//list creation
TSharedPtr<SCompoundWidget> GameDialog::CreateShipDesignParameters(UWorld* world) {
	UE_LOG(LogClass, Log, TEXT("GameDialog::CreateShipDesignParameters"));

	FString startType;
	ShipPropulsionItems.Empty();
	TWeakObjectPtr<UDataTable> dataTable = GameShipData::Get()->ShipPropulsionDataTable;
	if (dataTable.IsValid()) {
		TArray<FName> rowNames;
		dataTable->RowMap.GetKeys(rowNames);
		for(const auto& row : rowNames) {
			FShipPropulsionData* ptr = dataTable.Get()->FindRow<FShipPropulsionData>(row,row.ToString());
			if (ptr != nullptr) {
				if (startType.IsEmpty()) startType = ptr->PropulsionID;
				TSharedPtr<FShipPropulsionData> spd = MakeShareable(new FShipPropulsionData(*ptr));
				ShipPropulsionItems.Add(spd);
			}
		}
	}

	GenerateShipEngineList(startType);

	TSharedRef<SScrollBar> ExternalScrollbar1 = SNew(SScrollBar);
	TSharedRef<SScrollBar> ExternalScrollbar2 = SNew(SScrollBar);
	
	return
			(...)
			
			SAssignNew(EngineListView, SListView< TSharedPtr<FShipPropulsionData> >)
			.ExternalScrollbar( ExternalScrollbar1 )
			.ItemHeight(24)
			.ListItemsSource( &ShipPropulsionItems )
			.OnGenerateRow( this, &GameDialog::OnGeneratePropulsionList )
			.SelectionMode( ESelectionMode::Single )
			.OnSelectionChanged(this, &GameDialog::PropulsionEntrySelectionChanged)
			.HeaderRow	(
			
			(...)
	
}
	



Oh god, what a stupid mistake! I was assigning the propulsion listview to the engine variable… Works fine now with the following changes. Thanks for making me look more closely…



TSharedPtr<SListView< TSharedPtr<FShipPropulsionData> >> PropulsionListView;
TSharedPtr<SListView< TSharedPtr<FShipEngineData> >> EngineListView;
(...)
SAssignNew(PropulsionListView, SListView< TSharedPtr<FShipPropulsionData> >)
(...)
SAssignNew(EngineListView, SListView< TSharedPtr<FShipEngineData> >)