![]() |
VOOZH | about |
dotnet add package MyBase --version 2.0.0
NuGet\Install-Package MyBase -Version 2.0.0
<PackageReference Include="MyBase" Version="2.0.0" />
<PackageVersion Include="MyBase" Version="2.0.0" />Directory.Packages.props
<PackageReference Include="MyBase" />Project file
paket add MyBase --version 2.0.0
#r "nuget: MyBase, 2.0.0"
#:package MyBase@2.0.0
#addin nuget:?package=MyBase&version=2.0.0Install as a Cake Addin
#tool nuget:?package=MyBase&version=2.0.0Install as a Cake Tool
MyBase は .NET Framework, .NET Core による WPF アプリケーションの開発をサポートするためのライブラリです。
Prism と連携し標準機能を拡張する処理や、最新の Prism では廃止されてしまった実装の一部が移植されています。
| 対象のフレームワーク | バージョンの下限値 |
|---|---|
| .NET Framework | 4.8 |
| .NET Core | 3.1 |
| .NET | 5.0 |
ProductInfo クラスを利用することでエントリーポイントとなる実行ファイルのプロダクト情報を取得できます。このクラスは IProductInfo インターフェースを実装しており、他のサービスと同様にシングルトンとして DI コンテナに登録しておくと良いでしょう。
using MyBase;
using Prism.Ioc;
using Prism.Unity;
public partial class App : PrismApplication
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// シングルトンの登録
containerRegistry.RegisterSingleton<IProductInfo, ProductInfo>();
}
}
ViewModel 層では DI フレームワークからインスタンスを注入し、View 層でこれをバインドします。
using MyBase;
using Unity;
public class MainWindowViewModel : ViewModelBase
{
// インスタンスが注入されるプロパティ
[Dependency]
public IProductInfo ProductInfo { get; set; }
}
<Window x:Class="TestApp.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock Text="{Binding ProductInfo.Product, Mode=OneWay}"/>
</Grid>
</Window>
ProductInfo クラスは内部で遅延初期化される Assembly を保持しており、これをもとにプロダクト情報を取得しています。この Assembly の既定値は Assembly.GetEntryAssembly() と等価ですが、インスタンスの生成時にこの値を変更することもできます。
new ProductInfo(Assembly.GetExecutingAssembly());
Prism が提供する変更通知処理が搭載された BindableBase クラスを継承し、IDisposable, INotifyDataErrorInfo を実装した ValidatableBase があります。このクラスから派生し Model 層、ViewModel 層を実装できます。
using MyBase;
public abstract class ViewModelBase : ValidatableBase
{
}
public class MainWindowViewModel : ViewModelBase
{
private string _text;
// 変更通知プロパティ
public string Text
{
get => this._text;
set => this.SetProperty(ref this._text, value);
}
}
ValidatableBase は、同じく Prism の ErrorsContainer を内包しており、妥当性検証が必要なオブジェクトの基底クラスとして利用できます。たとえば以下のように、コンストラクタで ValidateProperties メソッドを呼び出すことで、インスタンスの生成と同時にプロパティの検証を行い、エラー情報を付与できます。
using System.ComponentModel.DataAnnotations;
public class MainWindowViewModel : ViewModelBase
{
private string _text;
// 検証属性が付与されたプロパティ
[Required]
public string Text
{
get => this._text;
set => this.SetProperty(ref this._text, value);
}
public MainWindowViewModel()
{
this.ValidateProperties();
}
}
また、リソースを一括で開放できる System.Reactive の CompositeDisposable がプロパティとして定義されています。ReactiveProperty 等を利用する際、定義されたプロパティの開放に使います。
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
public class MainWindowViewModel : ViewModelBase
{
// ReactiveProperty の宣言
public ReactiveProperty<bool> IsWorking { get; }
public MainWindowViewModel()
{
// ReactiveProperty の初期化と CompositeDisposable の紐づけ
this.IsWorking = new ReactiveProperty<bool>().AddTo(this.CompositeDisposable);
}
}
Prism 8.0 で廃止された ILoggerFacade インターフェース、Category, Priority を模した列挙値を提供します。
いくつかのロガーも移植されており、これらによって Prism のかつてのロギングと同等の実装が可能になります。
this.Logger = new DebugLogger();
this.Logger.Log("メッセージ", Category.Debug, Priority.None);
CompositeLogger は他のロガーを複数内包できるコンテナです。このクラス自身も ILoggerFacade を実装しており、実行される Log メソッドは内包されたすべてのロガーに伝播します。また同インターフェースにより DI コンテナへの登録も可能です。
this.Logger = new CompositeLogger(new DebugLogger(), new TraceLogger());
this.Logger.Log("メッセージ", Category.Debug, Priority.None);
using MyBase;
using Prism.Ioc;
using Prism.Unity;
public partial class App : PrismApplication
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// インスタンスの登録
containerRegistry.RegisterInstance(new CompositeLogger(new DebugLogger(), new TraceLogger()));
}
}
以前の Prism では InteractionRequest とそれに対応する Trigger による相互作用でダイアログを表示する方法が一般的でした。これが Prism 7.2 以降のバージョンでは新たに IDialogService インターフェースが追加され、こちらを使用する方法が推奨されるようになりました。
この方式を踏襲し、本ライブラリではコモンダイアログの表示に特化した ICommonDialogService、およびその実装である CommonDialogService を提供しています。CommonDialogService は Prism の DialogService を継承しているため、これに置き換えて使用することもできます。処理で授受される ICommonDialogParameters インターフェースを実装したいくつかのクラスが定義されており、現状では以下の機能が用意されています。
| パラメータ | 主な機能 |
|---|---|
| SaveFileDialogParameters | 保存先となるファイルパスの指定 |
| OpenFileDialogParameters | 読込元となるファイルパスの指定 |
| FolderBrowserDialogParameters | フォルダーパスの指定 |
| PrintDialogParameters | フロードキュメントの印刷 |
ダイアログを表示する
これらを使い ViewModel を起点に OpenFileDialog を表示する場合は以下のようになります。
using MyBase.Wpf;
using Unity;
public class MainWindowViewModel : ViewModelBase
{
[Dependency]
public ICommonDialogService CommonDialogService { get; set; }
/// <summary>
/// ファイルを選択するダイアログを表示します。
/// </summary>
public void ShowOpenFileDialog()
{
var parameters = new OpenFileDialogParameters()
{
InitialDirectory = root,
Filter = "すべてのファイル|*.*|テキストファイル|*.txt",
DefaultExtension = ".txt",
Multiselect = true,
};
var result = this.CommonDialogService.ShowDialog(parameters);
if (!result)
return;
var fileName = parameters.FileName;
}
}
コールバックメソッドを指定する
単純な表示だけなく、ダイアログを表示する前、閉じられた後に呼び出されるコールバックメソッドを引数で指定することもできます。以下は、OpenFileDialog に文字コードの選択欄を追加し、ユーザによって選択された文字コードを取得する例です。ダイアログの装飾には Windows API CodePack を使用しています。
using Microsoft.WindowsAPICodePack.Dialogs;
using Microsoft.WindowsAPICodePack.Dialogs.Controls;
using MyBase.Wpf;
using System.Linq;
using System.Text;
using Unity;
public class MainWindowViewModel : ViewModelBase
{
[Dependency]
public ICommonDialogService CommonDialogService { get; set; }
/// <summary>
/// ファイルを選択するダイアログを表示します。
/// </summary>
public void ShowOpenFileDialog()
{
IEnumerable<string> fileNames = null;
string filter = null;
Encoding encoding = null;
this.CommonDialogService.ShowDialog(
new OpenFileDialogParameters()
{
InitialDirectory = root,
Filter = "すべてのファイル|*.*|テキストファイル|*.txt",
DefaultExtension = ".txt",
Multiselect = true,
},
// ダイアログを表示する前に呼び出されるコールバックメソッド
(dialog, parameters) =>
{
// 文字コードの選択欄を追加する
var d = (CommonFileDialog)dialog;
var encodingComboBox = this.CreateEncodingComboBox(Encoding. UTF8);
var encodingGroupBox = new CommonFileDialogGroupBox($"文字コード (&E):");
encodingGroupBox.Items.Add(encodingComboBox);
d.Controls.Add(encodingGroupBox);
},
// ダイアログが閉じられた後に呼び出されるコールバックメソッド
(dialog, parameters, result) =>
{
if (result == false)
return;
var d = (CommonFileDialog)dialog;
var p = (OpenFileDialogParameters)parameters;
fileNames = p.FileNames;
filter = p.FilterName;
// 選択された文字コードを取得する
var encodingGroupBox = (CommonFileDialogGroupBox)d.Controls. First();
var encodingComboBox = (CommonFileDialogComboBox) encodingGroupBox.Items.First();
encoding = ((EncodingComboBoxItem)encodingComboBox.Items [encodingComboBox.SelectedIndex]).Encoding;
});
var result = this.CommonDialogService.ShowDialog(parameters);
if (!result)
return;
}
/// <summary>
/// 文字コード選択用のコンボボックスを構築します。
/// </summary>
/// <param name="defaultEncoding">既定の文字コード</param>
/// <returns>文字コード選択用のコンボボックス</returns>
public static CommonFileDialogComboBox CreateEncodingComboBox(Encoding defaultEncoding)
{
var comboBox = new CommonFileDialogComboBox();
var encodings = Constants.ENCODINGS;
for (var i = 0; i < encodings.Count(); i++)
{
comboBox.Items.Add(new EncodingComboBoxItem(encodings.ElementAt(i)) );
if (encodings.ElementAt(i) == defaultEncoding)
comboBox.SelectedIndex = i;
}
return comboBox;
}
/// <summary>
/// 文字コードを格納するコンボボックスアイテムを表します。
/// </summary>
private class EncodingComboBoxItem : CommonFileDialogComboBoxItem
{
public Encoding Encoding { get; }
public EncodingComboBoxItem(Encoding encoding)
: this(encoding, encoding?.EncodingName)
{
}
public EncodingComboBoxItem(Encoding encoding, string text)
: base(text)
{
this.Encoding = encoding;
}
}
}
IDialogService の追加に伴い Prism 8.0 で廃止された InteractionRequest の一連の処理が、本ライブラリに移植されています。
この InteractionRequest を用いて WPF 標準の MessageBox を使用したメッセージ表示する MessageAction を用意しました。MessageBox の引数を Xaml から指定できます。
View でメッセージを指定する場合
using MyBase.Wpf.InteractionRequest;
// 中略
public InteractionRequest<Confirmation> MessageRequest { get; } = new InteractionRequest<Confirmation>();
// 中略
this.MessageRequest.Raise(new Confirmation(), c =>
{
if (c.Confirmed == true)
// OK が選択されたときに実行する処理
});
<Window x:Class="TestApp.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mb="clr-namespace:MyBase.Wpf.InteractionRequest;assembly=MyBase">
<i:Interaction.Triggers>
<mb:InteractionRequestTrigger SourceObject="{Binding MessageRequest, Mode=OneWay}">
<mb:MessageAction
Title="タイトル"
Message="メッセージ"
Buttons="YesNo"
Image="Question"
DefaultResult="No"
Options="RightAlign"/>
</mb:InteractionRequestTrigger>
</i:Interaction.Triggers>
</Window>
ViewModel でメッセージを指定する場合
using MyBase.Wpf.InteractionRequest;
// 中略
public InteractionRequest<Confirmation> MessageRequest { get; } = new InteractionRequest<Confirmation>();
// 中略
this.MessageRequest.Raise(new Confirmation() { Title = "タイトル", Content = "メッセージ" }, c =>
{
if (c.Confirmed == true)
return;
});
<Window x:Class="TestApp.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mb="clr-namespace:MyBase.Wpf.InteractionRequest;assembly=MyBase">
<i:Interaction.Triggers>
<mb:InteractionRequestTrigger SourceObject="{Binding MessageRequest, Mode=OneWay}">
<mb:MessageAction
Buttons="YesNo"
Image="Question"
DefaultResult="No"
Options="RightAlign"/>
</mb:InteractionRequestTrigger>
</i:Interaction.Triggers>
</Window>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net5.0-windows7.0 net5.0-windows7.0 is compatible. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp3.1 netcoreapp3.1 is compatible. |
| .NET Framework | net48 net48 is compatible. net481 net481 was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.