1️⃣ ObservableRecipient 예제1. 시나리오

더보기

✔️ 1. 시나리오

 

  1. 버튼을 누르면
  2. 새창이 열림
  3. 문자열을 입력하고
  4. 버튼을 누르면 ViewModel 간 메시지를 주고받음
  5. MainViewModel이 메시지를 보내고, DetailViewModel이 받음

 

2️⃣ 프로젝트 구조

더보기

📁 프로젝트 구조

ProjectName/
├──📁Messages/
│   └── NameChangedMessage.cs
├──📁ViewModels/
│   ├── MainViewModel.cs
│   └── DetailViewModel.cs
├──📁Views/
│   ├── MainView.xaml
│   └── DetailView.xaml
├── App.xaml
└── App.xaml.cs


3️⃣  
Message 구현

더보기

📁 Message

using CommunityToolkit.Mvvm.Messaging.Messages;

// 이 클래스는 이름(Name) 문자열을 다른 ViewModel 또는 View에 전달하기 위한 메시지 클래스입니다.
// CommunityToolkit에서 제공하는 ValueChangedMessage<string>를 상속받아 생성합니다.
// string 타입의 값을 포함한 메시지를 보낼 때 사용할 수 있습니다.

// 예: WeakReferenceMessenger.Default.Send(new NameChangedMessage("홍길동"));
// 이 메시지를 받은 수신자는 메시지.Value를 통해 "홍길동" 값을 읽을 수 있습니다.

public class NameChangedMessage : ValueChangedMessage<string>
{
    // 생성자: 전달하고자 하는 string 값을 base 클래스에 전달하여 초기화합니다.
    public NameChangedMessage(string value) : base(value) { }
}


4️⃣   ViewModel 
구현

더보기

📁 MainViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel; // ObservableObject, ObservableProperty를 사용하기 위한 네임스페이스
using CommunityToolkit.Mvvm.Input;       // RelayCommand를 사용하기 위한 네임스페이스
using CommunityToolkit.Mvvm.Messaging;   // 메시지 기능을 위한 네임스페이스 (Messenger)

// MainViewModel 클래스는 사용자 입력 값을 저장하고, 버튼 클릭 시 해당 값을 다른 ViewModel로 전송하는 역할을 합니다.
// MVVM 패턴에서 View와 바인딩되며, ViewModel 간의 데이터 전달을 위해 메시지를 사용합니다.

public partial class MainViewModel : ObservableObject // ObservableObject를 상속받아 INotifyPropertyChanged 기능을 자동으로 구현
{
    // ObservableProperty 어트리뷰트는 아래의 name 필드에 대해 자동으로 Name 프로퍼티를 생성해줍니다.
    // 즉, public string Name { get; set; } 과 INotifyPropertyChanged 구현이 자동으로 이루어집니다.
    [ObservableProperty]
    private string name;

    // [RelayCommand]는 아래의 SendName() 메서드에 대응하는 ICommand 속성(SendNameCommand)을 자동 생성해줍니다.
    // 버튼 등 UI 요소에서 이 커맨드를 바인딩하여 클릭 시 메서드를 실행할 수 있게 됩니다.
    [RelayCommand]
    private void SendName()
    {
        // WeakReferenceMessenger는 메시지를 전송하고 수신할 수 있게 해주는 싱글턴 메시지 허브입니다.
        // 현재 Name 속성의 값을 NameChangedMessage로 래핑해서 전송합니다.
        // 이 메시지를 수신하는 ViewModel(예: DetailViewModel)은 메시지를 받아서 자신의 속성에 반영할 수 있습니다.
        WeakReferenceMessenger.Default.Send(new NameChangedMessage(Name));
    }
}

 

 

📁 DetailViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel; // ObservableRecipient, ObservableProperty를 위한 네임스페이스
using CommunityToolkit.Mvvm.Messaging;   // 메시지 수신(Messenger) 기능을 위한 네임스페이스

// DetailViewModel 클래스는 메시지를 수신하고 받은 데이터를 화면(View)에 표시하는 역할을 합니다.
// ObservableRecipient를 상속받아 메시지를 수신할 수 있으며, 수신 조건은 IsActive 속성으로 제어됩니다.
// 또한 ObservableObject 기능을 포함하여 속성 변경을 UI에 자동 반영할 수 있습니다.

public partial class DetailViewModel : ObservableRecipient, IRecipient<NameChangedMessage>
{
    // ObservableProperty 어트리뷰트를 사용하면, 자동으로
    // public string ReceivedName { get; set; } 와 INotifyPropertyChanged 구현이 생성됩니다.
    // UI는 이 속성을 바인딩하여 값을 자동으로 표시합니다.
    [ObservableProperty]
    private string receivedName;

    // 생성자: ViewModel이 활성화되었음을 알리는 IsActive를 true로 설정합니다.
    // IsActive가 true여야 메시지 수신이 작동하며, 메시지 시스템과 연결됩니다.
    public DetailViewModel()
    {
        IsActive = true; // 메시지를 수신할 준비 완료
    }

    // IRecipient<NameChangedMessage> 인터페이스 구현
    // 다른 ViewModel에서 NameChangedMessage 메시지를 보냈을 때 이 메서드가 호출됩니다.
    // message.Value를 통해 전송된 문자열을 읽고 ReceivedName 속성에 반영합니다.
    public void Receive(NameChangedMessage message)
    {
        // 받은 메시지 값을 문자열에 포함시켜 화면에 보여줄 텍스트로 구성합니다.
        ReceivedName = $"이름이 변경됨: {message.Value}";
    }
}


5️⃣  
View 구현

더보기

📁 MainWindow

    xmlns:vm="clr-namespace:WpfMvvmToolkit07_ObservableRecipient01.ViewModels"
    Title="Main View" Height="200" Width="300">

<Window.DataContext>
    <vm:MainViewModel />
</Window.DataContext>

<StackPanel Margin="20">
    <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" 
             Margin="0,0,0,10"/>
    <Button Content="이름 전송" Command="{Binding SendNameCommand}" Margin="0,0,0,10"/>
    <Button Content="상세보기 창 열기" Click="OpenDetailWindow"/>
</StackPanel>

 


📁 MainWindow - CodeBehind

private void OpenDetailWindow(object sender, RoutedEventArgs e)
{
    var DetailWindow = new DetailWindow();
    DetailWindow.Show();
}

 

 

📁 DetailWindow

    xmlns:vm="clr-namespace:WpfMvvmToolkit07_ObservableRecipient01.ViewModels"
    Title="Detail View" Height="200" Width="300">

<Window.DataContext>
    <vm:DetailWindowModel />
</Window.DataContext>

<Grid>
    <TextBlock Text="{Binding ReceivedName}" 
               HorizontalAlignment="Center"
               VerticalAlignment="Center"
               FontSize="16" FontWeight="Bold" />
</Grid>