如何绑定到列表视图的OnItemSelectionChanged

时间:2019-06-03 06:27:50

标签: c++ delegates unreal-engine4

在虚幻引擎4中,我想将事件绑定到glcm31,glcm32,glcm33,glcm34。该事件a10:a13需要一个UListView::OnItemSelectionChanged,所以我将一个指针传递给列表视图的列表条目类(我的自定义类来自FOnItemSelectionChanged)作为参数。

NullableItemType

但是,IUserObjectListEntry调用会导致错误

  

C2228:“ .__ Internal_AddDynamic”的左侧必须位于类/结构/联合中

所以我想我要绑定的回调函数(UCLASS() class PROJECT_API UMyListViewEntry : public UUserWidget, public IUserObjectListEntry { GENERATED_BODY() // Members and functions don't matter here. }; UCLASS() class PROJECT_API UMyUserWidget : public UUserWidget { GENERATED_BODY() void NativeConstruct() final { MyList->OnItemSelectionChanged.AddDynamic(this, &UMyUserWidget::MyEventCallback); } void MyEventCallback(UMyListViewEntry* e) { // implementation details } private: UPROPERTY(meta = (BindWidget)) UListView* MyList; }; )的签名是错误的。

应该绑定到AddDynamic()的函数的正确签名是什么?

1 个答案:

答案 0 :(得分:0)

这不仅与回调的签名有关,而且与如何添加回调有关。

选项1:使用OnItemSelectionChanged的返回值(回调将限于UObject)

UListView中,其成员OnItemSelectionChanged是通过宏IMPLEMENT_TYPED_UMG_LIST实现的,

virtual FOnItemSelectionChanged& OnItemSelectionChanged() const override { return OnItemSelectionChangedEvent; }

因此要将回调函数添加到委托中,请使用返回值:

UCLASS()
class PROJECT_API UMyUserWidget : public UUserWidget
{
    GENERATED_BODY()
    void NativeConstruct() final
    {
        auto event = MyList->OnItemSelectionChanged();
        event.AddUObject(this, &UMyUserWidget::MyEventCallback);
    }
    void MyEventCallback(UObject* e)
    {
        // implementation details, cast e to UMyListViewEntry*
    }
    // ...
};

您只能使用以UObject*作为参数的回调(UListView是使用UObject作为输入类型的基类的特殊化。)

蓝图(BP_OnItemSelectionChanged)中可用的委托是私有的,因此无法使用。

选项2:定义自定义委托

如果您想直接在回调中使用自定义条目类型作为参数,则可以

  1. 实现自己的列表视图或
  2. UListView派生并在virtual void OnSelectionChangedInternal(UObject* FirstSelectedItem)中调用自定义委托

虽然第一种方法类似于UListView的实现,但是第二种方法很简短,可能看起来类似于BP_OnItemSelectionChanged

DECLARE_MULTICAST_DELEGATE_TwoParams(FOnMyListItemSelectionChanged, UMyListViewEntry*, bool);
UCLASS(meta = (EntryInterface = UserObjectListEntry, EntryClass = UMyListViewEntry))
class PROJECT_API UMyListView : public UListView
{
    GENERATED_BODY()
public:
    FOnMyListItemSelectionChanged OnMyListItemSelectionChanged;
private:
    void OnSelectionChangedInternal(UObject* FirstSelectedItem) override
    {
        Super::OnSelectionChangedInternal(FirstSelectedItem);
        auto entry = Cast<UMyListViewEntry>(FirstSelectedItem);
        OnMyListItemSelectionChanged.Broadcast(entry, entry != nullptr);
    }
};
UCLASS()
class PROJECT_API UMyUserWidget : public UUserWidget
{
    GENERATED_BODY()
    void NativeConstruct() final
    {
        MyList->OnMyListItemSelectionChanged.AddUObject(this, &UMyUserWidget::MyEventCallback);
    }
    void MyEventCallback(UMyListViewEntry* e, bool isSelected)
    {
        // implementation details
    }
private:
    UPROPERTY(meta = (BindWidget), meta = (EntryClass = UMyListViewEntry))
    UMyListView* MyList;
};