MVVM (Prism) を使用してウィンドウ ダイアログを表示する例はありますか? - たとえば、コマンド実行時の構成設定ウィンドウ。
私が見たすべての例は、問題のないメディエーター パターンを使用していますが、それらはすべて理想的ではないビュー モデルのビューへの参照も持っています (DataTemplates を使用しています)。
ありがとう
ダイアログを表示するためにサービスを使用します。その後、サービスはビューをビューモデルにリンクすることもできます。
public interface IDialogService {
void RegisterView<TView, TViewModel>() where TViewModel:IDialogViewModel;
bool? ShowDialog(IDialogViewModel viewModel);
}
public interface IDialogViewModel {
bool CanClose();
void Close();
}
RegisterView
ビュータイプをViewModelタイプにリンクするだけです。これらのリンクは、モジュールの初期化で設定できます。これは、モジュールにアプリケーションの最上位層にデータテンプレートを登録させるよりも簡単です。
ShowDialog
表示するViewModelを表示します。Window.ShowDialog
メソッドと同じように、closeに対してtrue、false、およびnullを返します。実装はTView
、コンテナからタイプの新しいビューを作成し、それを提供されたViewModelに接続して、表示するだけです。
IDialogViewModel
ViewModelが検証を実行し、ダイアログの終了をキャンセルするためのメカニズムを提供します。
コンテンツコントロールを備えた標準のダイアログウィンドウがあります。がShowDialog
呼び出されると、新しい標準ダイアログが作成され、ビューがコンテンツコントロールに追加され、ViewModelが接続されて表示されます。標準ダイアログには、から適切なメソッドを呼び出すための適切なロジックを備えた[OK]ボタンと[キャンセル]ボタンがすでにありますIDialogViewModel
。
これを行う方法は、メディエーター パターンも使用することです。ViewModel がダイアログを表示したい場合、アプリケーションのメイン ウィンドウによって取得されるメッセージを送信します。メッセージには、ダイアログで使用される ViewModel のインスタンスが含まれています。
次に、メイン ウィンドウはダイアログ ウィンドウのインスタンスを構築し、ビュー モデルをそれに渡し、ダイアログを表示します。ダイアログの結果は、元のメッセージで発信者に返されます。
次のようになります。
あなたのビューモデルで:
DialogViewModel viewModel = new DialogViewModel(...);
ShowDialogMessage message = new ShowDialogMessage(viewModel);
_messenger.Broadcast(message);
if (message.Result == true)
{
...
}
メイン ウィンドウの分離コード:
void RecieveShowDialogMessage(ShowDialogMessage message)
{
DialogWindow w = new DialogWindow();
w.DataContext = message.ViewModel;
message.Result = w.ShowDialog();
}
これがあなたにアイデアを与えるのに十分であることを願っています...
サービスを使用してMVVMパターンに従ってダイアログを表示することが最も簡単な解決策であることに同意します。しかし、自分のプロジェクト Model、ViewModel、View に 3 つのアセンブリがある場合、MVVM パターン アセンブリ ViewModel には Model への参照があり、View は Model と ViewModel の両方に DialogService クラスをどこに配置すればよいでしょうか? ViewModel アセンブリに配置する場合、DialogView インスタンスを作成する機会はありません。一方、View アセンブリに DialogService を配置する場合、ViewModel クラスにどのように挿入すればよいでしょうか?
したがって、 Prism Part: Using Interaction Request Objects を使用した高度な MVVM シナリオを参照することをお勧めします。
このアプローチの例として:
DialogViewModelBase
public abstract class DialogViewModelBase : ViewModelBase
{
private ICommand _ok;
public ICommand Ok
{
get { return _ok ?? (_ok = new DelegateCommand(OkExecute, CanOkExecute)); }
}
protected virtual bool CanOkExecute()
{
return true;
}
protected virtual void OkExecute()
{
_isSaved = true;
Close = true;
}
private ICommand _cancel;
public ICommand Cancel
{
get
{
return _cancel ?? (_cancel = new DelegateCommand(CancelExecute, CanCancelExecute));
}
}
protected virtual bool CanCancelExecute()
{
return true;
}
protected virtual void CancelExecute()
{
Close = true;
}
private bool _isSaved = false;
public bool IsSaved
{
get { return _isSaved; }
}
private bool _close = false;
public bool Close
{
get { return _close; }
set
{
_close = value;
RaisePropertyChanged(() => Close);
}
}
}
CreateUserStoryViewModel:
public class CreateUserStoryViewModel : DialogViewModelBase
{
private string _name = String.Empty;
public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged(() => Name);
}
}
}
CreateUserStoryRequest
private InteractionRequest<Notification> _createUserStoryRequest;
public InteractionRequest<Notification> CreateUserStoryRequest
{
get
{
return _createUserStoryRequest ?? (_createUserStoryRequest = new InteractionRequest<Notification>());
}
}
CreateUserStory コマンド
private void CreateUserStoryExecute()
{
CreateUserStoryRequest.Raise(new Notification()
{
Content = new CreateUserStoryViewModel(),
Title = "Create User Story"
},
notification =>
{
CreateUserStoryViewModel createUserStoryViewModel =
(CreateUserStoryViewModel)notification.Content;
if (createUserStoryViewModel.IsSaved)
{
_domainContext.CreateUserStory(
new UserStory(){ Name = createUserStoryViewModel.Name, });
}
});
}
XAML:
<!--where xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ir="clr-namespace:Microsoft.Practices.Prism.Interactivity.InteractionRequest;assembly=Microsoft.Practices.Prism.Interactivity"-->
<i:Interaction.Triggers>
<ir:InteractionRequestTrigger SourceObject="{Binding CreateUserStoryRequest}">
<ir:PopupChildWindowAction>
<ir:PopupChildWindowAction.ChildWindow>
<view:CreateUserStory />
</ir:PopupChildWindowAction.ChildWindow>
</ir:PopupChildWindowAction>
</ir:InteractionRequestTrigger>
</i:Interaction.Triggers>
上記のコメントを理解したように、質問はダイアログを表示することではなく、ダイアログを非表示にすることです。この問題を解決するには、次の2つの方法があります。
標準のダイアログウィンドウを使用して、ビューを実装します。これには、ViewModelがViewを参照せずに閉じても問題ないことをViewに通知できるように、ViewとViewModelの間で疎結合の通信方法が必要になります。
それを可能にする複数のフレームワークが存在します-Prismのイベントアグリゲーターはそのうちの1つです。このシナリオでは、Viewはイベント(たとえば、MyDialogResultValidated)をサブスクライブし、イベントを受信すると、DialogResultをそれに応じて設定します。検証が成功した場合、ViewModel(そのSaveCommand内)はイベントを発生させます。
ビューを実装するために標準のダイアログウィンドウを使用しないでください。これには、モダリティを効果的にエミュレートするオーバーレイが必要になります。
このシナリオでは、ビューとオーバーレイの可視性は、SaveCommand実装によって、またはViewModelがビューを表示する必要があるときはいつでもそれに応じて設定されるViewModelのIsVisibleプロパティにバインドされます。
最初のアプローチでは、コードビハインドに少しのコードを含める必要があり、グローバルイベントを追加する必要があり、(おそらく)MVVMっぽくありません。2番目のアプローチでは、オーバーレイの実装(または他の誰かの実装の使用)が必要になりますが、コードビハインドにコードを含める必要はなく、グローバルイベントを行う必要もありません。また、(議論の余地はありますが)MVVMっぽいです。 。
次のサンプル アプリケーションに興味があるかもしれません。
http://compositeextensions.codeplex.com
Prism2 と PresentationModel (別名 MVVM) パターンを使用します。サンプル アプリケーションには、モーダル ダイアログが含まれています。
これは Prism ではありませんが、このMVVM デモには、完全に MVVM であるオプション ダイアログがあります。