namespace WPF_ToolKit04_06.Model
{
// User 클래스는 MVVM 아키텍처에서 Model 역할을 수행합니다.
// 이 클래스는 사용자 데이터를 표현하며, ViewModel과 Service에서 데이터를 주고받는 데 사용됩니다.
public class User
{
// 사용자 이름을 저장하는 속성입니다.
// 기본값은 빈 문자열로 초기화되어 있으며, 비어 있는 상태에서도 안전하게 사용 가능합니다.
public string Name { get; set; } = string.Empty;
}
}
🔍2.3Interface 만들기
using WPF_ToolKit04_06.Model;
namespace WPF_ToolKit04_06.Service
{
// IUserService 인터페이스는 사용자 정보를 가져오는 서비스를 정의합니다.
// MVVM 패턴에서 ViewModel은 이 인터페이스에 의존함으로써
// 구현체(UserService)에 대한 직접적인 의존을 피하고 느슨한 결합(Loosely Coupled)을 유지할 수 있습니다.
// 테스트 또는 확장 시 다양한 구현체(UserServiceMock 등)를 대체하여 활용할 수 있습니다.
public interface IUserService
{
// 비동기 방식으로 현재 사용자 정보를 가져오는 메서드 정의입니다.
// 실제 구현은 UserService 클래스에서 담당하며, API 또는 데이터베이스에서 데이터를 가져올 수 있습니다.
Task<User> GetCurrentUserAsync();
}
}
🔍2.4Service 클래스 만들기
public class UserService : IUserService
{
// GetCurrentUserAsync 메서드는 사용자 정보를 비동기적으로 반환합니다.
// 실제 프로젝트에서는 이 메서드가 데이터베이스, 웹 API, 파일 등에서 데이터를 로드하도록 구현됩니다.
// 여기서는 Task.Delay를 통해 2초간 지연시켜 비동기 처리의 흐름을 학습할 수 있도록 구성되어 있습니다.
public async Task<User> GetCurrentUserAsync()
{
await Task.Delay(2000); // 사용자 정보 로딩 시뮬레이션 (예: API 호출 대기)
// 사용자 정보를 담은 User 객체를 반환합니다.
// 실습 목적상 정적인 데이터를 반환하지만, 실제 구현에서는 외부 소스에서 가져온 데이터를 기반으로 구성됩니다.
return new User { Name = "홍길동" };
}
}
🔍2.5 ViewModel 클래스 만들기
using WPF_ToolKit04_06.Model;
using WPF_ToolKit04_06.Service;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace WPF_ToolKit04_06.ViewModel
{
// MainViewModel 클래스는 MVVM 패턴에서 ViewModel에 해당하며,
// View와 Model(Service) 사이의 데이터 바인딩과 명령 처리를 담당합니다.
// ObservableObject를 상속받아 속성 변경 알림(INotifyPropertyChanged)을 자동으로 처리합니다.
public partial class MainViewModel : ObservableObject
{
// IUserService 인터페이스를 통해 사용자 정보를 제공받는 의존성 주입 필드입니다.
// ViewModel은 인터페이스에만 의존하고 구체적인 구현은 외부에서 주입되므로 테스트와 유지보수에 유리합니다.
private readonly IUserService userService;
// 생성자에서 IUserService 구현체를 주입받아 ViewModel 내부에서 사용할 수 있게 합니다.
public MainViewModel(IUserService userService)
{
this.userService = userService;
}
// 사용자 인사 메시지를 저장하는 속성입니다.
// ObservableProperty 특성을 사용하면 자동으로 Greeting 속성이 생성되고
// 속성 값 변경 시 View에 자동으로 알림이 전파됩니다.
[ObservableProperty]
private string? greeting;
// GreetUser는 버튼 클릭 시 실행될 비동기 명령 메서드입니다.
// [RelayCommand] 특성을 사용하면 GreetUserCommand 또는 GreetUserCommandAsync 같은 ICommand 속성이 자동 생성됩니다.
// async 메서드를 사용하므로 CommunityToolkit은 내부적으로 AsyncRelayCommand를 생성합니다.
// 실행 중에는 명령이 자동으로 비활성화되어 중복 실행을 방지합니다.
[RelayCommand]
private async Task GreetUser()
{
Greeting = "사용자 정보를 가져오는 중...";
Console.WriteLine(Greeting);
// 서비스에서 사용자 정보를 비동기로 가져옵니다 (예: API 호출, DB 조회 등)
User user = await userService.GetCurrentUserAsync();
// 사용자 이름을 포함한 인사 메시지를 설정하고, UI에 자동 반영됩니다.
Greeting = $"안녕하세요, {user.Name}님!";
Console.WriteLine(Greeting);
}
}
}
🔍2.6 XAML 화면 구성
Title="GreetApp" Height="200" Width="300">
<StackPanel Margin="20" VerticalAlignment="Center">
<!--
버튼 UI 요소.
Content: 버튼에 표시될 텍스트.
Command: ViewModel에 정의된 GreetUser 메서드에서 생성된 GreetUserCommand 속성과 바인딩됨.
[RelayCommand] 특성이 붙은 GreetUser 메서드는 MVVM Toolkit이 자동으로 GreetUserCommand라는 ICommand 속성을 생성해 줌.
사용자가 버튼을 클릭하면 GreetUserCommand가 실행되고, ViewModel에서 사용자 정보를 비동기로 가져와 인사 메시지를 구성함.
-->
<Button Content="사용자에게 인사하기"
Command="{Binding GreetUserCommand}"
Margin="0,0,0,10" />
<!--
사용자에게 인사 메시지를 보여주는 TextBlock.
Text 속성이 ViewModel의 Greeting 속성과 바인딩되어 있음.
ViewModel의 Greeting 속성이 변경되면 INotifyPropertyChanged에 의해 UI가 자동으로 갱신됨.
FontWeight="Bold": 텍스트 강조
FontSize="14": 글자 크기
TextWrapping="Wrap": 텍스트가 길 경우 자동 줄바꿈
-->
<TextBlock Text="{Binding Greeting}"
FontWeight="Bold"
FontSize="14"
TextWrapping="Wrap"/>
</StackPanel>
✔️ 결과
항목 클릭 시 ViewModel.SelectedItem이 변경되며, 해당 항목의 IsSelected가 true가 됩니다.
// 사용자 정보 로딩 서비스
public class UserService : IUserService
{
public async Task<User> GetCurrentUserAsync()
{
await Task.Delay(2000); // 사용자 정보 로딩 지연 시뮬레이션
return new User { Name = "홍길동" };
}
}
public partial class MainViewModel : ObservableObject
{
[RelayCommand]
private async Task GreetUser()
{
Greeting = "사용자 정보를 가져오는 중...";
Console.WriteLine(Greeting);
// 서비스에서 사용자 정보를 비동기로 가져옵니다 (예: API 호출, DB 조회 등)
User user = await userService.GetCurrentUserAsync();
Greeting = $"안녕하세요, {user.Name}님!";
Console.WriteLine(Greeting);
}
}