반응형
mvvm을 사용할 때, Dialog용 Service를 만들어서 사용하는 방법을 기술하겠다.
위의 구조대로 만들 예정이다. 만약 새로운 화면이 필요하다면 커스텀 DialogView를 이용하여 처리하면 된다.
IDialogWindow.cs
namespace CounterMonitor.Dialogs.Service
{
public interface IDialogWindow
{
bool? DialogResult { get; set; }
object DataContext { get; set; }
bool? ShowDialog();
}
}
창을 띄울 화면 생성
DialogWindow.xaml
<Window x:Class="CounterMonitor.Dialogs.Service.DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CounterMonitor.Dialogs.Service"
mc:Ignorable="d"
Title="{Binding Title}"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
Height="300" Width="300">
<ContentControl x:Name="ContentPresenter" Content="{Binding}"/>
</Window>
해당 위의 인터페이스를 상속하자
DialogWindow.xaml.cs
using System.Windows;
namespace CounterMonitor.Dialogs.Service
{
/// <summary>
/// DialogWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class DialogWindow : Window, IDialogWindow
{
public DialogWindow()
{
InitializeComponent();
}
}
}
DialogWindow에 바인딩할 기초 ViewModel 생성
DialogViewModelBase.cs
namespace CounterMonitor.Dialogs.Service
{
public abstract class DialogViewModelBase<T>
{
public string Title { get; set; }
public string Message { get; set; }
public T DialogResult { get; set; }
public DialogViewModelBase() : this(string.Empty, string.Empty) { }
public DialogViewModelBase(string title) : this(title, string.Empty) { }
protected DialogViewModelBase(string title, string message)
{
Title = title;
Message = message;
}
public void CloseDialogWithResult(IDialogWindow dialog, T result)
{
DialogResult = result;
if (dialog != null)
{
dialog.DialogResult = true;
}
}
}
}
호출할 ViewModel에서 사용할 Service Interface 선언
IDialogService.cs
namespace CounterMonitor.Dialogs.Service
{
public interface IDialogService
{
T OpenDialog<T>(DialogViewModelBase<T> viewModel);
}
}
실제 객체 선언
DialogService.cs
namespace CounterMonitor.Dialogs.Service
{
public class DialogService : IDialogService
{
public T OpenDialog<T>(DialogViewModelBase<T> viewModel)
{
IDialogWindow window = new DialogWindow();
window.DataContext = viewModel;
window.ShowDialog();
return viewModel.DialogResult;
}
}
}
이제 기본 골격 완성되었다. 간단한 Alert 다이어로그를 만들어보자.
Dialog 결과를 받을 enum 선언
DialogResults.cs
namespace CounterMonitor.Dialogs
{
public enum DialogResults
{
Undefined,
Yes,
No
}
}
DialogWindow.xaml에 띄울 usercontrol 생성
AlertDialogView.xaml
<UserControl x:Class="CounterMonitor.Dialogs.Alert.AlertDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CounterMonitor.Dialogs.Alert"
mc:Ignorable="d"
Height="100" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Text="{Binding Message}"
HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap"/>
<Button Grid.Row="1"
Content="OK"
Command="{Binding OKCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/>
</Grid>
</UserControl>
AlertDialogView에 바인딩할 ViewModel 생성
AlertDialogViewModel.cs
using CounterMonitor.Dialogs.Service;
using Prism.Commands;
namespace CounterMonitor.Dialogs.Alert
{
public class AlertDialogViewModel : DialogViewModelBase<DialogResults>
{
public DelegateCommand<IDialogWindow> OKCommand { get; private set; }
public AlertDialogViewModel(string title, string message) : base(title, message)
{
OKCommand = new DelegateCommand<IDialogWindow>(OnOKCommand);
}
private void OnOKCommand(IDialogWindow window)
{
CloseDialogWithResult(window, DialogResults.Undefined);
}
}
}
ViewModel과 view 링크처리
App.xaml
<Application x:Class="CounterMonitor.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CounterMonitor"
xmlns:alert="clr-namespace:CounterMonitor.Dialogs.Alert"
StartupUri="View/MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<!-- Theme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
<DataTemplate DataType="{x:Type alert:AlertDialogViewModel}">
<alert:AlertDialogView/>
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
실제 사용할 ViewModel에서 호출
MainWindowViewModel.cs
namespace CounterMonitor.ViewModel
{
class MainWindowViewModel : BindableBase
{
private IDialogService _dialogService;
public DelegateCommand TestCommand { get; private set; }
public MainWindowViewModel()
{
_dialogService = new DialogService();
TestCommand = new DelegateCommand(OnTesetCommnad);
}
private void OnTesetCommnad()
{
var dialog = new AlertDialogViewModel("Attention", "this is an alert!");
var result = _dialogService.OpenDialog(dialog);
}
}
}
끝!!
반응형
'프로그래밍 > WPF' 카테고리의 다른 글
[WPF] ItemControl에서 Item Index binding (0) | 2021.05.11 |
---|---|
[WPF] Value Converter (0) | 2021.05.10 |
[WPF] Separator Vertial 처리 (0) | 2021.05.06 |
[WPF] IGrouping 데이터 바인딩 하기 (0) | 2021.05.06 |
[WPF] MVVM에서 ComboBox SelectionChanged Binding (0) | 2020.08.21 |