문제

WPF 응용 프로그램이 있습니다 viewModel에서 다시 MessageBox.Show ()를 호출합니다. (사용자가 실제로 삭제하고 싶은지 확인하려면). 이것은 실제로 작동합니다, 하지만 MVVM의 곡물에 반대합니다 ViewModel이보기에서 어떤 일이 발생하는지 명시 적으로 결정해서는 안됩니다.

그래서 지금 나는 생각하고있다 messagebox.show () 함수를 가장 잘 구현하려면 어떻게해야합니까? 내 MVVM 응용 프로그램에서 옵션 :

  1. 나는 "당신은 확실합니까 ...?" 두 개의 버튼과 함께 예와 아니오 모두 내 XAML의 테두리에있는 모든 것과 템플릿에 트리거를 만들어 areyoursuredialogueboxisvisible, 그런 다음이 대화 상자가 필요할 때 areyoursuredialogueboxisvisible을 "true"에 할당하고 내 뷰 모델의 DelegateCommand를 통해 두 버튼을 처리합니다.

  2. xaml의 트리거로 어떻게 든 이것을 처리하려고 시도 할 수 있으므로 삭제 버튼이 실제로 메시지와 버튼과 함께 일부 테두리 요소가 나타나고 예 버튼이 실제로 삭제되었습니다.

두 솔루션 모두 너무 복잡한 것 같습니다 MessageBox.show ()가있는 몇 줄의 코드 라인이었던 것.

MVVM 응용 프로그램에서 어떤 방법으로 대화 상자를 성공적으로 구현 했습니까?

도움이 되었습니까?

해결책

당신이 언급 한 두 사람 중 옵션 #2를 선호합니다. 페이지의 삭제 버튼은 "삭제 대화 상자 확인"이 나타납니다. "삭제 대화 상자 확인"은 실제로 삭제를 시작합니다.

Karl Shifflett 's를 확인 했습니까? WPF 비즈니스 슬라이드 및 데모 라인? 나는 그가 이런 일을한다는 것을 안다. 나는 어디서 기억하려고 노력할 것이다.

편집 : MVVM에서 Demo #11 "데이터 검증"(editContActItemsControlSelectionViewModel.deleteCommand)을 확인하십시오. Karl은 ViewModal에서 팝업을 호출합니다 (What!? :-). 나는 실제로 당신의 아이디어를 더 좋아합니다. 단위 테스트가 더 쉬운 것 같습니다.

다른 팁

구조 서비스. 사용 오닉스 (면책 조항, 저는 저자입니다) 이것은 다음과 같이 쉽습니다.

public void Foo()
{
    IDisplayMessage dm = this.View.GetService<IDisplayMessage>();
    dm.Show("Hello, world!");
}

실행중인 응용 프로그램에서는 간접적으로 MessageBox.Show ( "Hello, World!")를 호출합니다. 테스트 할 때 IDISPlayMessage 서비스를 조롱하고 ViewModel에 제공하여 테스트 중에 달성하고자하는 일을 수행 할 수 있습니다.

그의 링크가 Kaput이라는 Dean Chalk의 답변을 확장하려면 :

app.xaml.cs 파일에서 확인 대화 상자를 ViewModel에 연결합니다.

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;
    ...
}

View (mainWindowView.xaml)에는 viewModel에서 명령을 호출하는 버튼이 있습니다.

<Button Command="{Binding Path=DeleteCommand}" />

ViewModel (MainWindowViewModel.cs)은 대의원 명령을 사용하여 "확실합니까?" 대화하고 동작을 수행하십시오. 이 예에서는 a입니다 SimpleCommand 비슷하다 이것, 그러나 ICOMMAND의 구현은해야합니다.

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 특정 항목을 사용하여 구현할 수 있습니다 (사용합니다. 이것은 CodePlex에 있습니다 일부 남자는 Prajeesh라고 불렀습니다).

그렇게하면 모든 것이 분리되고 테스트 가능합니다.

같은 이벤트를 제기하는 것은 어떻습니까? "MessageBoxRequested" View의 CodeBehind에서 처리됩니다 (어쨌든보기 전용 코드이므로 CodeBehind 에이 코드를 사용하는 데 아무런 문제가 없습니다).

순수한 MVVM 솔루션에서 사용하고 여전히 단위 테스트 기능을 허용하기 위해 간단한 MessageBox 래퍼 컨트롤을 만들었습니다. 세부 사항은 내 블로그에 있습니다 http://geekswithblogs.net/mukapu/archive/2010/03/12/user-prompts-messagebox-with-mvvm.aspx

무카푸

ViewModel의 메시지를 듣는 동작을 구현했습니다. Laurent Bugnion 솔루션을 기반으로하지만 코드를 사용하지 않고 재사용 가능하기 때문에 더 우아하다고 생각합니다.

여기에서 확인하십시오

WPF 및 Silverlight 메시지 상자

MVVM이 지원되었습니다

http://slwpfmessagebox.codeplex.com/

다른 사람이 여전히 읽고 불만족스러운 경우를 대비하여 :

나는 단지 '알림'유형 MessageBox를 처리하고 싶었습니다 (예 : 나는 신경 쓰지 않습니다. DialogResult), 그러나 내가 읽은 대부분의 솔루션에서 가지고있는 문제는 그들이 당신이 당신이 당신의 뷰 구현을 선택하도록 간접적으로 강요하는 것처럼 보인다는 것입니다 (즉, 현재는 내가 가지고 있습니다. MessageBox.Show, 그러나 나중에 내 관점에서 숨겨진 패널의 가시성으로 바이올린을 바이올린으로 결정하면 INotification 인터페이스가 뷰 모델로 전달되었습니다).

그래서 나는 빠르고 더러워졌다 :

뷰 모델에는 a가 있습니다 string NotificationMessage 변경 사항이 통지 된 속성 PropertyChanged.

뷰는 가입합니다 PropertyChanged, 그리고 그것이 본 경우 NotificationMessage 재산은 통과하고 원하는대로합니다.

좋아, 그래서 이것은 뷰에 코드-비만이 있고 이름이 PropertyChanged 하드 코딩되었지만 어쨌든 XAML에서 하드 코딩 될 것입니다. 그리고 그것은 가시성을 위해 변환기와 같은 모든 것들을 피하고, 알림이 여전히 보이는지 여부를 말하는 속성을 피합니다.

(이것은 제한된 유스 케이스 (화재와 잊어 버린)를위한 것입니다. 나는 그것을 확장하고 싶은 방법에 대해 많은 생각을하지 않았습니다.)

나는 단지 VM에서 던질 것입니다. 나는 다른 사람의 서비스를 사용하거나 메시지 상자를 던지기 위해 내 자신을 쓰고 싶지 않습니다.

나는 최근 에이 문제를 발견했으며, MessageBox.show를 뷰 모델의 전체 MVVM 불만 메시지 상자 메커니즘으로 교체해야했습니다.

이것을 달성하기 위해 내가 사용했습니다 InteractionRequest<Notification> 그리고 InteractionRequest<Confirmation> 상호 작용과 함께 메시지 상자에 대한 내 자신의 견해를 썼습니다.

내가 구현 한 내용이 게시됩니다 여기

이 주제에 대한 답이 너무 많아 사용자 정의 클래스 생성과 타사 라이브러리 사용에 이르기까지 다양합니다. 멋진 영상으로 멋진 팝업을 원한다면 타사 도서관을 사용한다고 말합니다.

그러나 WPF 앱 용 Microsoft의 일반 메시지 상자를 사용하려면 여기 MVVM/Unit Test Friendly 구현이 있습니다.

처음에 나는 메시지 상자에서 물려 받고 인터페이스로 그것을 줄이겠다고 생각했지만 메시지 상자가 공개 생성자가 없기 때문에 "쉬운"솔루션은 다음과 같습니다.

Visual Studio에서 메시지 상자를 디 컴파일하는 모든 메소드 오버로드를 볼 수 있습니다. 원하는 방법을 확인한 다음 새 클래스를 만들고 메소드를 추가하고 인터페이스와 TA-DA로 포장했습니다! 이제 Ninject를 사용하여 인터페이스와 클래스를 바인딩하고 주입하고 MOQ를 사용하여 단위 테스트 등을 사용할 수 있습니다.

인터페이스를 만듭니다 (모두 필요하지 않아 오버로드 중 일부 만 추가) :

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);
        }
    }

이제 주사 할 때 이것을 사용하고 붐 u는 트릭을 수행 할 수있는 어리석은 추상화가 있습니다. 이는 사용할 위치에 따라 괜찮습니다. 내 사례는 간단한 앱으로 몇 가지 작업을 수행하는 것만이므로 솔루션을 엔지니어링 할 수 없습니다. 이것이 누군가를 돕기를 바랍니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top