어떻게 MessageBox를 성공적으로 구현했습니까?MVVM에 () 기능을 표시하시겠습니까?
MessageBox를 호출하는 WPF 애플리케이션이 있습니다.View Model(보기 모델)에 ()을 다시 표시합니다(사용자가 정말 삭제할지 확인).이는 실제로 작동하지만, View 모델이 View에서 수행되는 작업을 명시적으로 결정하지 않아야 하기 때문에 MVVM의 세부 사항에 반하는 것입니다.
그래서 저는 어떻게 하면 MessageBox를 가장 잘 구현할 수 있을지 고민하고 있습니다.내 MVVM 응용 프로그램에 () 기능 표시, 옵션:
"정말요?"라는 메시지를 보낼 수 있습니다.XAML에서 경계에 모두 있음 및 없음 단추 두 개와 함께 템플릿에 트리거를 만들어 AreYourSureDialogBoxIsVisible이라는 ViewModel 속성을 기반으로 축소/표시되도록 한 다음 이 대화 상자가 필요할 때 Assign YourSureDialogBoxIsVisible을 "true"로 지정합니다.또한 View Model에서 Delegate Command를 통해 두 버튼을 처리할 수 있습니다.
또한 XAML의 트리거를 사용하여 이 문제를 처리할 수도 있습니다. 그러면 Delete(삭제) 버튼은 실제로 메시지와 버튼이 포함된 Border 요소를 표시하고 Yes(예) 버튼은 실제로 삭제를 수행할 수 있습니다.
두 솔루션 모두 MessageBox를 사용하는 코드 몇 줄에 비해 너무 복잡한 것 같습니다.표시().
MVVM 애플리케이션에서 대화 상자를 성공적으로 구현한 방법은 무엇입니까?
구조에 도움이 됩니다.Onyx(Disclaimer, 내가 저자)를 사용하면 다음과 같이 간단합니다.
public void Foo()
{
IDisplayMessage dm = this.View.GetService<IDisplayMessage>();
dm.Show("Hello, world!");
}
실행 중인 응용 프로그램에서는 MessageBox를 간접적으로 호출합니다.쇼("안녕, 세상!").테스트할 때 IDdisplayMessage 서비스를 조롱하여 ViewModel에 제공하여 테스트 중에 수행하고자 하는 모든 작업을 수행할 수 있습니다.
당신이 언급한 두 가지 중에서, 저는 2번 옵션을 선호합니다.페이지의 [삭제] 단추를 누르면 "삭제 확인 대화상자"가 나타납니다.삭제 확인 대화상자가 실제로 삭제를 시작합니다.
Karl Shiflett의 WPF Line Of Business 슬라이드 및 데모를 확인해 보셨습니까?저는 그가 이런 일을 한다는 것을 압니다.어디 있는지 기억해 볼게요.
편집: 데모 #11 "MVVM의 데이터 유효성 검사"(연락처 항목 제어 선택 보기 모델 편집)를 확인합니다.명령 삭제).Karl이 ViewModal(ViewModal)에서 팝업을 호출합니다(What!? :-).저는 사실 당신의 아이디어가 더 마음에 들어요.유닛 테스트가 더 쉬워 보입니다.
그의 링크가 엉망이 된 지금 딘 초크의 답변을 확대하기 위해:
App.xaml.cs 파일에서 확인 대화상자를 뷰 모델에 연결합니다.
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var confirm = (Func<string, string, bool>)((msg, capt) => MessageBox.Show(msg, capt, MessageBoxButton.YesNo) == MessageBoxResult.Yes);
var window = new MainWindowView();
var viewModel = new MainWindowViewModel(confirm);
window.DataContext = viewModel;
...
}
보기(MainWindowView.xaml)에는 ViewModel의 명령을 호출하는 버튼이 있습니다.
<Button Command="{Binding Path=DeleteCommand}" />
뷰 모델(MainWindowViewModel.cs )은 위임 명령을 사용하여 "확실합니까?" 대화 상자를 표시하고 작업을 수행합니다.에서는 이예는에서다같습니다과음다▁a같니▁in▁is습▁this▁it다입니다.SimpleCommand이와 유사하지만 I 명령의 구현이 수행되어야 합니다.
private readonly Func<string, string, bool> _confirm;
//constructor
public MainWindowViewModel(Func<string, string, bool> confirm)
{
_confirm = confirm;
...
}
#region Delete Command
private SimpleCommand _deleteCommand;
public ICommand DeleteCommand
{
get { return _deleteCommand ?? (_deleteCommand = new SimpleCommand(ExecuteDeleteCommand, CanExecuteDeleteCommand)); }
}
public bool CanExecuteDeleteCommand()
{
//put your logic here whether to allow deletes
return true;
}
public void ExecuteDeleteCommand()
{
bool doDelete =_confirm("Are you sure?", "Confirm Delete");
if (doDelete)
{
//delete from database
...
}
}
#endregion
VM에 주입되는 인터페이스(IMessageDisplay 등)를 생성하기만 하면 MessageBox(ShowMessage() 등)와 같은 메서드가 있습니다.표준 메시지 상자를 사용하거나 WPF에 특정한 것을 사용하여 구현할 수 있습니다(나는 이것을 Prajeesh의 CodePlex에서 사용합니다).
그렇게 하면 모든 것이 분리되고 테스트 가능합니다.
같은 이벤트를 개최하는 것은 어떻습니까?"MessageBoxRequested"View 뒤의 코드에서 처리됩니다(어쨌든 View만 코드이므로 코드 뒤에 이 코드가 있는 것에 문제가 없습니다).
다른 사람이 아직도 책을 읽고 만족하지 못하는 경우:
저는 단지 '알림' 유형의 MessageBox를 처리하고 싶었습니다(즉, 저는 그것에 대해 신경쓰지 않습니다).DialogResult), 을 선택하도록 하는 것 , 현재 입니다).MessageBox.Show하지만 나중에 내 보기에서 숨겨진 패널의 가시성을 직접 만지작거리기로 결정하면, 그것은 매우 잘 맞물리지 않을 것입니다.INotification인터페이스가 ViewModel(ViewModel)로 전달되었습니다.
그래서 나는 빠르고 더러운 것을 추구했습니다.
에는 View가 .string NotificationMessage 내용이 속변, 내경이로 PropertyChanged.
는 보기구대를 합니다.PropertyChanged그리고 만약 그것이 본다면.NotificationMessage재산은 들어오고, 원하는 것은 무엇이든 합니다.
좋아요, 그러면 보기에 코드백이 있고 이름이PropertyChanged하드 코드화되어 있지만 어쨌든 XAML에서는 하드 코드화되어 있을 것입니다.이는 가시성을 위한 변환기와 알림이 여전히 표시되는지 여부를 나타내는 속성과 같은 모든 것을 피한다는 것을 의미합니다.
(이것은 단지 제한된 사용 사례(fire and forget)를 위한 것임을 인정하며, 어떻게 확장할지에 대해 많은 생각을 하지 않았습니다.)
이 항목에는 사용자 지정 클래스 만들기부터 타사 라이브러리 사용까지 다양한 답변이 있습니다.멋진 비주얼의 멋진 팝업을 원한다면 타사 라이브러리를 사용하는 것이 좋습니다.
그러나 WPF 앱에 Microsoft의 일반 메시지 상자를 사용하려는 경우 MVVM/유닛 테스트에 적합한 구현이 있습니다.
처음에는 메시지 상자에서 상속받아 인터페이스로 포장할 것이라고 생각했지만, 메시지 상자에 공용 생성자가 없기 때문에 그럴 수 없었습니다. 그래서 "쉬운" 해결책이 여기 있습니다.
비주얼 스튜디오에서 메시지 상자를 디컴파일하면 모든 메소드 오버로드를 볼 수 있습니다. 저는 어떤 메소드를 원하는지 확인하고 새로운 클래스를 만들고 메소드를 추가하여 인터페이스와 ta-da로 포장했습니다!이제 inject를 사용하여 인터페이스와 클래스를 바인딩하고 주입한 다음 Moq를 사용하여 test e.t.c.를 단위로 지정할 수 있습니다.
인터페이스 만들기(모든 오버로드가 필요하지 않기 때문에 일부 오버로드만 추가됨):
public interface IMessageBox
{
/// <summary>Displays a message box that has a message, title bar caption, and button; and that returns a result.</summary>
MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button);
/// <summary>Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.</summary>
MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon);
/// <summary>Displays a message box that has a message and title bar caption; and that returns a result.</summary>
MessageBoxResult Show(string messageBoxText, string caption);
}
그런 다음 이 클래스에서 상속받을 클래스는 다음과 같습니다.
public class MessageBoxHelper : IMessageBox
{
/// <summary>Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.</summary>
public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button,
MessageBoxImage icon)
{
return MessageBox.Show(messageBoxText, caption, button, icon, MessageBoxResult.None,
MessageBoxOptions.None);
}
/// <summary>Displays a message box that has a message, title bar caption, and button; and that returns a result.</summary>
public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button)
{
return MessageBox.Show(messageBoxText, caption, button, MessageBoxImage.None, MessageBoxResult.None,
MessageBoxOptions.None);
}
/// <summary>Displays a message box that has a message and title bar caption; and that returns a result.</summary>
public MessageBoxResult Show(string messageBoxText, string caption)
{
return MessageBox.Show(messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None,
MessageBoxResult.None, MessageBoxOptions.None);
}
/// <summary>Displays a message box that has a message and that returns a result.</summary>
public MessageBoxResult Show(string messageBoxText)
{
return MessageBox.Show(messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None,
MessageBoxResult.None, MessageBoxOptions.None);
}
}
자, 이것을 사용해서 심전도를 주입하고 부메랑은 약삭빠르고 추상적인 방법으로 치료할 수 있습니다.어디에 쓰느냐에 따라 괜찮습니다.제 경우는 몇 가지 작업만 수행할 수 있는 간단한 앱이므로 솔루션을 엔지니어링하는 것이 좋습니다.이것이 누군가에게 도움이 되기를 바랍니다.
순수 MVVM 솔루션에서 사용할 수 있도록 간단한 MessageBox 래퍼 컨트롤을 만들었으며 유닛 테스트 기능도 허용합니다.자세한 내용은 제 블로그 http://geekswithblogs.net/mukapu/archive/2010/03/12/user-prompts-messagebox-with-mvvm.aspx 에 있습니다.
무카푸
WPF 및 실버라이트 메시지 상자
MVVM 지원
http://slwpfmessagebox.codeplex.com/
VM에서 삭제할 수도 있습니다.저는 단지 메시지 박스를 던지기 위해 다른 사람의 서비스를 사용하거나 제 서비스를 작성해야 하는 것을 원하지 않습니다.
최근에 MessageBox를 교체해야 하는 문제를 발견했습니다.전체 MVVM 불만 메시지 상자 메커니즘을 사용하여 View Model에 표시합니다.
이를 달성하기 위해 사용했습니다.InteractionRequest<Notification>그리고.InteractionRequest<Confirmation>상호 작용 트리거와 함께 메시지 상자에 대한 나만의 보기를 작성했습니다.
구현한 내용은 여기에 게시되어 있습니다.
이 아이디어는 MessageBox를 처리하는 서비스 등을 보기 모델에 추가하는 것이 아닙니다.보기 모델이 여전히 MessageBox 표시를 간접적으로 처리하기 때문에 MVVM을 위반합니다.뷰 모델은 뷰에 대해 아무것도 모르고 데이터 관리에 집중해야 합니다.또한 보기 구성요소의 표시를 관리하는 것은 보기의 책임입니다.
따라서 뷰가 뷰 모델을 관찰하도록 한 다음, 뷰에 대한 UI 로직을 관찰을 기반으로 수행해야 합니다.ViewModel의 이벤트를 듣고 이벤트의 인수를 기반으로 MessageBox를 표시하는 방법도 있습니다.
이는 이러한 목표를 달성하는 방법을 보여주는 하나의 예에 불과하며, 자신의 필요와 목적에 맞게 맞춤화하고 활용할 수 있습니다.
주 창.xaml
<Window x:Class="MessageBoxMVVMExample.MainWindow"
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:MessageBoxMVVMExample"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<TextBox Text="{Binding Input}"/>
<Button Content="Submit" Command="{Binding SubmitCommand}"/>
</StackPanel>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
private BaseViewModel _viewModel = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = _viewModel;
_viewModel.NewMessageDialog += OnNewMessageDialog;
}
private void OnNewMessageDialog(MessageDialogEventArgs args)
{
// you can also put it on a service to achieve decoupling
MessageBox.Show(args.Message, args.MessageType.ToString());
}
}
MainWindowViewModel.cs
public class MainWindowViewModel : BaseViewModel
{
private string _input = String.Empty;
public string Input
{
get => _input;
set
{
_input = value;
OnPropertyChanged(new(nameof(Input)));
}
}
public RelayCommand SubmitCommand => new(o => ValidateNumeric());
public void ValidateNumeric()
{
decimal dec;
if (decimal.TryParse(Input, out dec))
{
OnNewMessageDialog(new(MessageType.SUCCESS, "Yes, it's a valid number!"));
}
else
{
OnNewMessageDialog(new(MessageType.ERROR, "No, it's an invalid number!"));
}
}
}
BaseViewModel.cs
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public event MessageDialogEventHandler? NewMessageDialog;
protected void OnPropertyChanged(PropertyChangedEventArgs args)
{
PropertyChanged?.Invoke(this, args);
}
protected void OnNewMessageDialog(MessageDialogEventArgs args)
{
NewMessageDialog?.Invoke(args);
}
}
public enum MessageType {
INFO,
ERROR,
WARNING,
SUCCESS
}
public class MessageDialogEventArgs
{
public MessageType MessageType { get; set; } = MessageType.INFO;
public string Message { get; set; } = string.Empty;
public MessageDialogEventArgs(MessageType messageType, string message)
{
MessageType = messageType;
Message = message;
}
}
public delegate void MessageDialogEventHandler(MessageDialogEventArgs messageDialogEventArgs);
RelayCommand.cs
public class RelayCommand : ICommand
{
private Action<object> _callback;
private Func<object, bool>? _canExecute;
public event EventHandler? CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> callback, Func<object, bool>? canExecute)
{
this._callback = callback;
this._canExecute = canExecute;
}
public RelayCommand(Action<object> callback) : this(callback, null) { }
public bool CanExecute(object? parameter)
{
return this._canExecute == null || this._canExecute(parameter);
}
public void Execute(object? parameter)
{
this._callback(parameter);
}
}
정상 작동 중 [MVVM]
if (System.Windows.MessageBox.Show("Are you need to delete?", "",
System.Windows.MessageBoxButton.YesNo) == System.Windows.MessageBoxResult.Yes)
{
// Do your action
}
언급URL : https://stackoverflow.com/questions/1098023/how-have-you-successfully-implemented-messagebox-show-functionality-in-mvvm
'programing' 카테고리의 다른 글
| Azure DevOps - YAML 대신 GUI를 사용하여 빌드 파이프라인을 편집합니다. (0) | 2023.04.27 |
|---|---|
| Azure 웹사이트에서 machineKey를 설정하는 방법 (0) | 2023.04.27 |
| 웹 서버가 응답하기를 기다리는 bash에서 루프를 만드는 방법은 무엇입니까? (0) | 2023.04.27 |
| VBA에서 "메모리 부족 오류"를 방지하기 위해 메모리를 지우는 방법은 무엇입니까? (0) | 2023.04.27 |
| Azure 파이프라인에서 현재 작업 디렉토리 변경 (0) | 2023.04.27 |