[언리얼 MVVM 바인딩 필드 Select 처리] 3. MVVM Binding Selection → Widget Hierarchy 양방향 동기화

KWONYEONGMIN·2026년 3월 13일

언리얼

목록 보기
14/15

동작 흐름

  • MVVM Binding Panel에서 특정 Row를 클릭하면,
  • 해당 Row가 가리키는 WidgetName을 계산하고,
  • Widget Hierarchy에서 동일 위젯이 Selected 상태로 표시되도록 동기화된다.

진입점 : Binding Panel Row 클릭 이벤트

MVVM Binding Panel에서 Row를 클릭하면 SBindingsList::OnSourceListSelectionChanged가 호출된다.

void SBindingsList::OnSourceListSelectionChanged(TSharedPtr<FBindingEntry> Entry, ESelectInfo::Type SelectionType) const

이 함수는 Binding Panel의 선택 상태가 변경될 때 실행되는 핵심 콜백이며
선택된 Binding 정보를 SBindingsPanel로 전달하는 역할을 한다.
내부에서는 현재 선택된 항목을 순회하면서 RowType에 따라 다른 데이터를 생성한다.

RowType에 따른 동작

FBindingEntry::ERowType에 따라 처리 방식이 달라진다.

RowType동작
Group위젯 단위 그룹 Row
Binding실제 ViewBinding
ConditionBinding 조건
EventViewModel 이벤트

예를 들어,

  • ERowType::Group 를 클릭하는 경우에는 case문을 타지 않고 SelectionVariants 생성 없이 바로 아래 로직으로 진행(혹은 사실상 아무것도 안 하고) 된다.
  • ERowType::Binding 를 클릭하는 경우에는 Entry->GetBinding(View)를 통해 FMVVMBlueprintViewBinding*을 얻어 SelectionVariants에 담아 SBindingsPanel로 전달한다.

Hierarchy 동기화 로직 추가

기존에 있던 선택 함수 내에서 구현을 하게 되면 아래와 같은 조건에서 구현이 실행되어야 한다.

  • 단일 선택일 때만 동기화 수행
  • RowType에 따라 WidgetName을 계산
    • Group 클릭 시: Entry->GetGroupName()
    • Binding 클릭 시: SelectedBinding->DestinationPath.GetWidgetName()

구현 코드는 다음과 같다.


	...

if (SelectedEntries.Num() <= 1)
{
	FName WidgetName = NAME_None;
	if (Entry->GetRowType() == FBindingEntry::ERowType::Group)
	{
		WidgetName = Entry->GetGroupName();
	}
	else if (Entry->GetRowType() == FBindingEntry::ERowType::Binding)
	{
		if (FMVVMBlueprintViewBinding* SelectedBinding = Entry->GetBinding(View))
		{
			WidgetName = SelectedBinding->DestinationPath.GetWidgetName();
		}
	}
	if(false == WidgetName.IsNone())
	{
		SelectWidgetInHierarchy(WidgetName);
	}
}
...

이 로직을 통해 Binding Panel에서 선택된 Row가 어떤 위젯과 연결되어 있는지 계산할 수 있다.


WidgetName → Widget Hierarchy 선택 반영

SelectWidgetInHierarchy 함수는
WidgetName을 기반으로 Widget Hierarchy 선택을 변경한다.

  1. WidgetBlueprint의 WidgetTree에서 Template Widget을 찾고
  2. Template → FWidgetReference 변환한 뒤
  3. FWidgetBlueprintEditor::SelectWidgets로 Hierarchy 선택을 갱신한다.
void SBindingsList::SelectWidgetInHierarchy(FName InWidgetName) const
{
	TSharedPtr<FWidgetBlueprintEditor> Editor = WeakBlueprintEditor.Pin();
	if (false == Editor.IsValid() || InWidgetName.IsNone())
	{
		return;
	}

	UWidgetBlueprint* BP = Editor->GetWidgetBlueprintObj();
	if (nullptr == BP || nullptr == BP->WidgetTree)
	{
		return;
	}

	// 1) 이름으로 위젯 템플릿 찾기
	UWidget* Template = BP->WidgetTree->FindWidget(InWidgetName);
	if (nullptr == Template)
	{
		UE_LOG(LogTemp, Warning, TEXT("FindWidget failed: %s"), *InWidgetName.ToString());
		return;
	}

	// 2) Template -> FWidgetReference 만들기
	TSet<FWidgetReference> ToSelect;
	auto MakeWidgetReferenceSet =
		[](const TSharedPtr<FWidgetBlueprintEditor>& InEditor, UWidget* InTemplate, TSet<FWidgetReference>& OutSet) -> bool
		{
			if (false == InEditor.IsValid() || nullptr == InTemplate)
			{
				return false;
			}

			FWidgetReference ref = InEditor->GetReferenceFromTemplate(InTemplate);

			if (false == ref.IsValid())
			{
				return false;
			}

			OutSet.Add(ref);
			return true;
		};

	if (false == MakeWidgetReferenceSet(Editor, Template, ToSelect))
	{
		UE_LOG(LogTemp, Warning, TEXT("MakeWidgetReferenceSet failed: %s"), *InWidgetName.ToString());
		return;
	}

	// 3) 하이라키 선택 반영
	Editor->SelectWidgets(ToSelect, false);
}

FWidgetReference 생성 방식

  • FWidgetReference는 직접 생성하거나 수정할 수 없다.
  • FWidgetReferenceFWidgetBlueprintEditor와 friend 관계로 설계되어 있기 때문에 Editor를 통해서만 유효한 Reference를 생성할 수 있다.

따라서

Editor->GetReferenceFromTemplate(Template);

을 사용해 안정적으로 reference를 생성해야 한다.


정리

이 구현을 통해 다음과 같은 양방향 동기화가 가능해졌다.

Widget Hierarchy 선택

MVVM Binding Panel Row 선택

MVVM Binding Panel Row 선택

Widget Hierarchy 위젯 선택

Hierarchy ↔ Binding Panel 사이의 선택 상태가 서로 동기화되는 Editor UX를 구현할 수 있었다.

profile
Hello World

0개의 댓글