티스토리 뷰
■ 목차
1. DialogManagerSample 들어가기
크로스플랫폼 닷넷 UI 프레임워크인 아바로니아 맛보기를 넘어서서 본격적인 활용에 들어가기 위한 학습 방법으로 필자는 예제 프로그램 리뷰를 하나씩 수행하기로 했다. 기술 자료가 넉넉하고, 비주얼스튜디오의 WPF 디자이너와 같은 도구가 있다면 넘어갈 수도 있는 문제겠지만 지금까지 접하지 않았던 새로운 도구와 친숙해지는 방법은 역시 예제를 통하는 것이 좋은 방법이 아닌가 싶다. 공식 예제 코드는 깃허브 https://github.com/AvaloniaUI/Avalonia.Samples 에서 받을 수 있다. 커뮤니티에서 발굴해 놓은 예제와 참조 프로젝트도 있는데 깃허브 https://github.com/AvaloniaCommunity/awesome-avalonia 에서 확인할 수 있다.

DialogManagerSample은 CommunityToolkit.Mvvm 패키지를 활용하는 예제로, MVVM 응용에서 대화창을 띄우기 위해 다이얼로그 매니저라 부르는 서비스를 작성하는 방법을 제시한다.
2. 프로그램 동작 및 구조

하단의 [Select Files] 버튼을 클릭하면 파일 선택 대화창이 나오고 한 개 이상의 파일을 선택하면 선택한 파일의 목록을 리스트박스에 표시하는 동작을 수행한다.

프로젝트는 MVVM 패턴에서 별도의 모델 없이 한 개의 뷰모델 및 뷰와 Services 폴더에 다이얼로그 매니저라 부르는 서비스를 포함하는 구성이다.
3. 대화창 서비스 구현 방법
public class DialogManager
{
private static readonly Dictionary<object, Visual> RegistrationMapper = new Dictionary<object, Visual>();
static DialogManager()
{
RegisterProperty.Changed.AddClassHandler<Visual>(RegisterChanged);
}
private static void RegisterChanged(Visual sender, AvaloniaPropertyChangedEventArgs e)
{
if (sender is null)
{
throw new InvalidOperationException("The DialogManager can only be registered on a Visual");
}
if (e.OldValue != null)
{
RegistrationMapper.Remove(e.OldValue);
}
if (e.NewValue != null)
{
RegistrationMapper.Add(e.NewValue, sender);
}
}
public static readonly AttachedProperty<object?> RegisterProperty = AvaloniaProperty.RegisterAttached<DialogManager, Visual, object?>("Register");
public static void SetRegister(AvaloniaObject element, object value)
{
element.SetValue(RegisterProperty, value);
}
public static object? GetRegister(AvaloniaObject element)
{
return element.GetValue(RegisterProperty);
}
public static Visual? GetVisualForContext(object context)
{
return RegistrationMapper.TryGetValue(context, out var result) ? result : null;
}
public static TopLevel? GetTopLevelForContext(object context)
{
return TopLevel.GetTopLevel(GetVisualForContext(context));
}
}
public static class DialogHelper
{
public static async Task<IEnumerable<string>?> OpenFileDialogAsync(this object? context, string? title = null, bool selectMany = true)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var topLevel = DialogManager.GetTopLevelForContext(context);
if(topLevel != null)
{
var storageFiles = await topLevel.StorageProvider.OpenFilePickerAsync(
new FilePickerOpenOptions()
{
AllowMultiple = selectMany,
Title = title ?? "Select any file(s)"
});
return storageFiles.Select(s => s.Name);
}
return null;
}
}
서비스 코드는 뷰와 연결되는 DialogManager 클래스와 뷰모델에서 버튼 클릭 시 대화창을 여는 작업을 수행하는 DialogHelper 클래스로 구성된다.
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:DialogManagerSample.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:services="using:DialogManagerSample.Services"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="DialogManagerSample.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
x:CompileBindings="True"
services:DialogManager.Register="{Binding}"
Icon="/Assets/avalonia-logo.ico"
Title="DialogManagerSample">
준비한 서비스 클래스는 뷰에서 "xmlns:services"로 서비스의 네임 스페이스를 지정하고 "services:..."으로 사용할 서비스를 등록한다.
public partial class MainWindowViewModel : ViewModelBase
{
[ObservableProperty]
private IEnumerable<string>? _SelectedFiles;
[RelayCommand]
private async Task SelectFilesAsync()
{
SelectedFiles = await this.OpenFileDialogAsync("Hello Avalonia");
}
}
뷰모델의 코드는 CommunityToolkit.Mvvm 패키지를 사용하는 방법으로 위의 코드처럼 어노테이션을 기술하는 방법으로 간편하게 속성과 명령을 기술할 수 있다. [ObservableProperty] 어노테이션으로 뷰에서는 SelectedFiles 속성을 바인딩할 수 있고, [RelayCommand] 어노테이션으로 뷰에서는 SelectFilesCommand를 명령으로 바인딩할 수 있다.
4. 뷰와 아발로니아 요소들
뷰는 텍스트 블록, 리스트 박스, 버튼이 그리드 형태로 구성된 단순한 형태이다.
<Grid RowDefinitions="Auto,*,Auto">
<TextBlock Text="Selected Files:" />
<ListBox ItemsSource="{Binding SelectedFiles}" Grid.Row="1" />
<Button Content="Select Files"
Command="{Binding SelectFilesCommand}"
Grid.Row="2" />
</Grid>
- Grid : https://api-docs.avaloniaui.net/docs/T_Avalonia_Controls_Grid
행과 열로 구성되는 표 형태의 영역을 정의하는 데 사용한다. RowDefinitions, ColumnDefinitions으로 행과 열의 크기를 지정. - TextBlock : https://api-docs.avaloniaui.net/docs/T_Avalonia_Controls_TextBlock
텍스트 출력, 태그 내에 출력할 문자열을 입력하거나 Text 속성에 정적/동적 텍스트 입력. FontWeight, FontSize, VerticalAlignment, TextAlignment, TextWrapping 등 사용. - ListBox : https://api-docs.avaloniaui.net/docs/T_Avalonia_Controls_ListBox
항목 선택이 가능한 목록 컨트롤. ItemsSource, SelectedItem, Background, Margin, ItemsPanel, ItemTemplate 등 사용 - Button : https://api-docs.avaloniaui.net/docs/T_Avalonia_Controls_Button
표준 버튼 컨트롤. HorizontalAlignment, VerticalAlignment, Content, Command, CommandParameter, IsVisible, FontSize, CornerRadius, Background, Classes 등 사용
'프로그래밍' 카테고리의 다른 글
| 아발로니아 UI 예제 프로그램 리뷰 7 - SimpleToDoList (0) | 2025.11.10 |
|---|---|
| 아발로니아 UI 예제 프로그램 리뷰 5 - MvvmDialogSample (0) | 2025.10.28 |
| 아발로니아 UI 예제 프로그램 리뷰 4 - ValueConversionSample (0) | 2025.10.27 |
| 아발로니아 UI 예제 프로그램 리뷰 3 - ValidationSample (0) | 2025.10.22 |
| 아발로니아 UI 예제 프로그램 리뷰 2 - CommandSample (0) | 2025.10.17 |