#やりたいこと
ViewModelからファイルダイアログを開く。
#実装
ファイルダイアログを開くアクションを作成する。
アクション
using Microsoft.Win32;
using Prism.Interactivity.InteractionRequest;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Interactivity;
namespace Sample {
public class PopupCommonDialogAction : TriggerAction<FrameworkElement> {
public static readonly DependencyProperty FileDialogTypeProperty
= DependencyProperty.Register(
nameof(FileDialogType),
typeof(Type),
typeof(PopupCommonDialogAction),
new PropertyMetadata(null));
public Type FileDialogType {
get { return (Type)GetValue(FileDialogTypeProperty); }
set { SetValue(FileDialogTypeProperty, value); }
}
protected override void Invoke(object parameter) {
var args = parameter as InteractionRequestedEventArgs;
if (args == null)
return;
var confirmation = args.Context as IConfirmation;
if (confirmation != null)
ShowDialog(confirmation);
args.Callback();
}
private void ShowDialog(IConfirmation confirmation) {
var dialog = (CommonDialog)Activator.CreateInstance(FileDialogType);
var confirmationProperties = confirmation.GetType().GetProperties();
var dialogProperties = dialog.GetType().GetProperties();
// ViewModelから渡された値をViewにセット
foreach (var prop in confirmationProperties) {
var value = prop.GetValue(confirmation, null);
if (value == null)
continue;
var dialogProp = dialogProperties
.FirstOrDefault(p => p.Name.Equals(prop.Name, StringComparison.OrdinalIgnoreCase));
if (dialogProp != null && dialogProp.CanWrite)
dialogProp.SetValue(dialog, value, null);
}
var ret = dialog.ShowDialog();
// Viewの値をViewModelに返す
foreach (var prop in dialogProperties) {
var ctxProp = confirmationProperties
.FirstOrDefault(p => p.Name.Equals(prop.Name, StringComparison.OrdinalIgnoreCase));
if (ctxProp != null && ctxProp.CanWrite)
ctxProp.SetValue(confirmation, prop.GetValue(dialog, null), null);
}
if (confirmation != null)
confirmation.Confirmed = ret == true;
}
}
}
通知クラス
using Prism.Interactivity.InteractionRequest;
namespace Sample {
public class FileDialogPropertyNotification : Confirmation {
//ファイルダイアログと同名のプロパティを定義する
public string FileName { get; set; }
public string Filter { get; set; }
//以下省略
}
}
#使い方
XAML
<Window x:Class="Sample.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:prism="http://prismlibrary.com/"
xmlns:win32="clr-namespace:Microsoft.Win32;assembly=PresentationFramework"
xmlns:local="clr-namespace:Sample"
Title="MainView" Height="300" Width="300">
<i:Interaction.Triggers>
<!--セーブファイルダイアログ-->
<prism:InteractionRequestTrigger SourceObject="{Binding OpenSaveFileDialogRequest, Mode=OneWay}">
<local:PopupCommonDialogAction FileDialogType="{x:Type win32:SaveFileDialog}"/>
</prism:InteractionRequestTrigger>
<!--オープンファイルダイアログ-->
<prism:InteractionRequestTrigger SourceObject="{Binding OpenOpenFileDialogRequest, Mode=OneWay}">
<local:PopupCommonDialogAction FileDialogType="{x:Type win32:OpenFileDialog}"/>
</prism:InteractionRequestTrigger>
</i:Interaction.Triggers>
<Grid>
<TextBox />
</Grid>
</Window>
ViewModel
using Prism.Interactivity.InteractionRequest;
using System.Windows;
namespace Sample {
public class MainViewModel {
public InteractionRequest<FileDialogPropertyNotification> OpenOpenFileDialogRequest { get; }
= new InteractionRequest<FileDialogPropertyNotification>();
public InteractionRequest<FileDialogPropertyNotification> OpenSaveFileDialogRequest { get; }
= new InteractionRequest<FileDialogPropertyNotification>();
private string OpenOpenFileDialog(string title, string filter, string fileName = "") {
var notification = new FileDialogPropertyNotification() {
Title = title,
Filter = filter,
FileName = fileName
};
OpenOpenFileDialogRequest.Raise(notification);
return notification.Confirmed ? notification.FileName : string.Empty;
}
private string OpenSaveFileDialog(string title, string filter, string fileName = "") {
var notification = new FileDialogPropertyNotification() {
Title = title,
Filter = filter,
FileName = fileName
};
OpenSaveFileDialogRequest.Raise(notification);
return notification.Confirmed ? notification.FileName : string.Empty;
}
}
}