List View ! Please help me implement It In C++

I do this simple guide here: [UE4]UE4.20で追加されたListViewウィジェットについて|株式会社ヒストリア . But that’s all in Blueprint.

https://historia.co.jp/wp/wp-content/uploads/2018/09/blogimg190922I.gif

EntryData (Widget):

https://historia.co.jp/wp/wp-content/uploads/2018/09/blogimg190922F-1024x229.png

Widget has ListView:

https://historia.co.jp/wp/wp-content/uploads/2018/09/blogimg190922H-1024x176.png

*** So, How to implement it in C++
- Event On List Item Object Interface ? Where , How?

Thank you?

1 Like

Have you tried using UUserWidget class ? Explore a bit, you can create them on runtime and add them to any other widget or directly viewport

Search engine source for “SListView” for examples.

You need a SListView, a shared FString array, and a ITableRow generator method:



TSharedPtr<SListView<TSharedPtr<FString>>> LineCounter;
TArray<TSharedPtr<FString>>LinesText;

TSharedRef<ITableRow>OnGenerateLineCounter( TSharedPtr<FString>Item, const TSharedRef<STableViewBase> & myTable );




TSharedRef<ITableRow>SMyWidget::OnGenerateLineCounter( TSharedPtr<FString>Item, const TSharedRef<STableViewBase> & myTable ) {
   return SNew(SComboRow<TSharedRef<FString>>, myTable)
   
       SNew(SBorder)
      .Padding(FMargin(5.f,0.f,5.f,0.f))
      
         SNew(STextBlock)
         .Text(FText::FromString( *Item.Get() ))
      ]
   ];
}




SAssignNew( LineCounter, SListView<TSharedPtr<FString>> )
   .OnGenerateRow(this, &SMyWidget::OnGenerateLineCounter)
   .ListItemsSource(&LinesText).ItemHeight(14)
   .SelectionMode(ESelectionMode::Single)


2 Likes

Thanks for your advice.


void UItemEntryWidget::NativeOnListItemObjectSet(UObject* ListItemObject)
{
UItemData* Data = Cast<UItemData>(ListItemObject);
ItemName->SetText(FText::FromString(Data->Text));
}



void UInventoryWidget::NativeConstruct()
{
ListViewItem->SetScrollbarVisibility(ESlateVisibility::Hidden);

for (size_t i = 0; i < 5; i++)
{
ItemData = NewObject<UItemData>(this);
ItemData->Text = FString::Printf(TEXT(" Old %d"), i);

ListViewItem->AddItem(ItemData);
}
}

But I execute this:


auto UWidgets = ListViewItem->GetDisplayedEntryWidgets();
UE_LOG(LogTemp, Warning, TEXT("UWidgets Size = %d"), UWidgets.Num());

**Result : 0. **

Maybe: not All EntryWidgets reference when Add Item. Any else help me?

Maybe you could try using bindwidget for displaying and you should use getnumitems to find the listview length.

自分はこのやり方でリストビューの内部テキストを変更いたしました。
I changed the internal text of the list view this way.

■.h

UPROPERTY()
UListView* UListViewTest = nullptr;

■.cpp

UListViewTest = Cast<UListView>(GetWidgetFromName(FName(TEXT("ListViewTest"))));
UListViewTest->OnEntryWidgetGenerated().AddLambda([](UUserWidget& uw)
{	
	auto* testex = Cast<UTextBlock>(uw.GetWidgetFromName(FName(TEXT("TextBlockTest"))));
	      testex->SetText(FText::AsNumber(50.f));
});

コールバックを設定して、リストに追加されたら追加されたウィジェットに変更を加えています。
I’m setting a callback and making changes to the added widget once it’s added to the list.




■追記-------------------------------------------------------------------------------------------------

もう一つの方法を見つけました。
I found another way.

リストビューに追加するwidgetにIUserObjectListEntryを継承して
Inherit IUserObjectListEntry to the widget to add to the list view

virtual void NativeOnListItemObjectSet(UObject* ListItemObject);

を使用する方法です。
This is the method to use.

■.h
> UCLASS()
 class MY_API UListViewWidgetClass : public UUserWidget, public IUserObjectListEntry
 {
GENERATED_BODY()

    UPROPERTY(EditAnywhere, meta = (BindWidget))
    UTextBlock* ListTextBlock = nullptr;

public:
	virtual void NativeOnListItemObjectSet(UObject* ListItemObject);

}
■.cpp
void UListViewWidgetClass::NativeOnListItemObjectSet(UObject* ListItemObject)
{
	auto* data = Cast<DataBaseTest>(ListItemObject);
	if (data)
	{
		ListTextBlock->SetText(FText::FromString(data->value));
	}
}

追加するためのデータは以下の様にします
The data to add is as follows

■.h
UCLASS()
class MY_API DataBaseTest: public UObject
{
	GENERATED_BODY()

public:
	FString value;
};

リストビューへの追加は以下の様にします
Add to the list view as follows

■.cpp
TArray<DataBaseTest*> Datas;

for (int i = 0; i < 10; i++)
{
	DataBaseTest* data = NewObject<DataBaseTest>();
	
	data->value = FString::Printf(TEXT("text%d"), i);
	Datas.Add(data);
}

if(UListViewTest)
{
    UListViewTest->ClearListItems();

    // ここで設定されたオブジェクトは「NativeOnListItemObjectSet」に渡されます
    // The object set here is passed to "NativeOnListItemObjectSet"
    UListViewTest->SetListItems(Datas);
}

2 Likes