【问题标题】:How to bind to OnItemSelectionChanged of a list view如何绑定到列表视图的 OnItemSelectionChanged
【发布时间】:2019-06-03 06:27:50
【问题描述】:

在虚幻引擎 4 中,我想将一个事件绑定到 UListView::OnItemSelectionChanged。该事件FOnItemSelectionChanged 需要NullableItemType,因此我将一个指向列表视图的列表条目类(我的自定义类派生自IUserObjectListEntry)的指针作为参数传递。

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() 调用会导致错误

C2228:“.__Internal_AddDynamic”的左侧必须在类/结构/联合中

所以我想,我要绑定的回调函数的签名(MyEventCallback())是错误的。

应该绑定到UListView::OnItemSelectionChanged 的函数的正确签名是什么?

【问题讨论】:

  • 想必OnItemSelectionChanged其实是某种getter,能不能像MyList->OnItemSelectionChanged().AddDynamic(...这么简单?
  • @George 是的,你是对的。我现在有三种不同的工作方法(其中一种使用那个事件获取器)。我想我会在有时间的时候添加一个答案。

标签: c++ delegates unreal-engine4


【解决方案1】:

不仅仅是回调的签名,还有如何添加回调。

选项#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;
};

【讨论】:

    猜你喜欢
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    • 2011-12-02
    • 2017-09-22
    • 2013-04-05
    • 2014-01-24
    • 2011-02-15
    相关资源
    最近更新 更多