このサンプル集は今のところ C# だけだが、他にも手を広げるかも。広げないかも。
リポジトリ: netsphere / dotnet-wpf-examples · GitLab
2023年3月現在, .NET 5 と .NET Core 3.1 はすでにサポート期限が切れている。クライアント側は、3rd party ライブラリや Microsoft のライブラリも、非互換のため .NET 6 で動かないものもある。
.NET Framework v4.7 で様子見も選択肢。ライブラリが上げられれば、パフォーマンス向上を享受できるので、.NET ヴァージョンを上げればよい。ただ、無理しなくてよい。
01_wpf-validation-rules/
INotifyPropertyChanged
インタフェイスを実装するのではなく, DependencyObject
class から派生させるべき。
<Window.DataContext>
で指定する。ここでの指定は, 原則として "型". インスタンスが自動的に生成される。View と view model は 1:1 になる。
IDataErrorInfo
インタフェイスは古い. INotifyDataErrorInfo
インタフェイスを実装する。もっと良いのは, ValidationRule
クラスから派生させ, XAML 側から検証器を指定する。入力コントロールごとの検証と, submit 時の検証とがある。
<Window.Resources>
内に <ControlTemplate>
要素を記述する。
次のように, XAML で検証器を指定する。
参考: Data validation in WPF | Magnus Montin
02_ListView-DataVirtualization/
ListView
のサンプル.
Forked from WPF: Data Virtualization - CodeProject Original license: public domain
表形式で大量のデータを表示する場合、データ全部をメモリに載せると大変。Data virtualization で, 表示するのに必要なデータだけ view model から提供する。
このサンプルでは比較のため, List<T>
(全部をメモリに載せる), VirtualizingCollection<T>
および AsyncVirtualizingCollection>T>
という3つのクラスを用意した。ListView.ItemsSource
プロパティに設定する,
ListView.ItemsSource
プロパティが受け付けるのは, 非ジェネリックな IEnumerable
. このプロパティにコレクションを set すると, 内部で ListView.Items
プロパティ (ItemCollection
型) に紐づけられ, ItemsSource モードになる。
非常に分かり辛くなっているのは, ItemsSource
プロパティには, コレクションだけでなく, コレクションを wrap した collection view を設定してもよいということ。コレクションを設定した場合は, 内部で collection view が自動生成される。
このサンプルは, コレクションを拡張する方向で作っている。Collection view を拡張するやり方は, サンプル #05 にて。
ItemsSource
に設定するオブジェクトによって, 内部で生成される collection view の型が変わってくる。相当ゴチャゴチャしていてよく分からないが、こうかな?
IListSource
: コレクションの GetList()
が IList
オブジェクトを返せば、それを使って再度、判定。
ICollectionView
collection view: それを使う.
ICollectionViewFactory
: CreateView()
する。戻り値は ICollectionView
型.
IBindingList
コレクション: BindingListCollectionView
で wrap.
IList
(非ジェネリック): ListCollectionView
で wrap.
IEnumerable
(非ジェネリック): internal class EnumerableCollectionView
で wrap.
イケてないが過去との互換性のため, コンテナが非ジェネリック版を強制される。IEnumerable
派生では機能が足りずエラーになったりするので, 拡張するときは, 非ジェネリックな IList
から派生させること。this[]
と GetEnumerator()
を実装する。
03_dotnet-http2-sample/
サーバに HTTP/2 でリクエストを投げるサンプル。 TargetFrameworkVersion: v4.7.2
Topic 1. MenuItem.Command
や Button.Command
の使い方。
ググると DelegateCommand
を使う例ばかりだが、妥当ではない。ショートカットキーの設定に <Window.InputBindings>
, <KeyBinding Key="B" Modifiers="Control" ...
のようにしたりするが、的外れ。
WPF の「コマンド」は, UI Text や Key Gesture (ショートカットキー) を定義する RoutedUICommand
オブジェクトと, それを command handler に紐づける CommandBinding
の二段階になっている。
"コマンド" として ApplicationCommands.Close
などの標準コマンドも使える。自作のコマンドは x:Static
で設定する。
これらのコマンドとハンドラとを CommandBinding
で結びつける。引数で canExecute
ハンドラも渡せる。
Topic 2. テキストフィールドの値によって, Command
プロパティを持つボタンの有効・無効を切り替える。
<TextBox>
に <Binding.ValidationRules>
でヴァリデータを設定する。
ICommand.CanExecute
に反映させたい。TextBox
は Validation.HasError
attached property があってエラーの有無を取れるが、bind できない。このようなときは behaviour を使う。ググると旧い System.Windows.Interactivity パッケージを使う例ばかり出てくる。そんなの不要。
なお, 今回の例では使わないが, System.Windows.Interactivity パッケージは廃れて, Microsoft.Xaml.Behaviors.Wpf パッケージが後継になっている。
ValidationBehavior
が作ったビヘイビア。似たような状況はサンプル #14 にもある。
<Button>
は ICommand.CanExecute
の状態変化に伴って、有効・無効が自動的に切り替わる。
Topic 3. HTTP/2 サポート。
.NET Framework 4.7 で HTTP/2 を使うには NuGet パッケージ System.Net.Http.WinHttpHandler の WinHttpHandler
クラスを使わなければならない。.NET Core 3.0 以降は素の HttpClient
でも HTTP/2 がサポートされる。
04_wpf-sample-for-calling-winrt-apis/
UWP アプリ用の API "Windows Runtime APIs" (WinRT APIs) を呼び出す。現代は, Microsoft.Windows.SDK.Contracts パッケージを使えばよい。
たとえば, Windows.Globalization.JapanesePhoneticAnalyzer
class で、日本語の形態素解析が手軽に可能。
Microsoft.Windows.SDK.Contracts のターゲット: `netstandard2.0` .. .NET Framework 4.6+, .NET Core 3.0+
ターゲットフレームワーク ".NET 6.0" 以降, ターゲット OS バージョンを 10.0.17763.0 (v1809) 以降だと、何もしなくても WinRT API が呼び出せるようになった。 .NET 5.0 の破壊的変更 (CoreCLR の変更) で、逆に, `Microsoft.Windows.SDK.Contracts` パッケージへの参照は削除しなければならない。
サンプル #09 も参照されたい。
05_DataGrid-DataVirtualization/
再び data virtualization について。今度は <DataGrid>
に適用する。以前のサンプルと異なり, collection view を拡張する方向。
<DataGrid>
は列ヘッダのクリックでソートできる。Data virtualization とどのように組み合わせるか。
Collection クラスではなく, collection view クラスを作り、これを DataGrid.ItemsSource
に bind する。手を抜くため, ListCollectionView
クラスから派生して最小限だけ override するのがよい。サンプル #02 も参照されよ。
07_SimpleGraphicEditor/
09_wpf-with-xaml-islands/
XAML 諸島のサンプル。サンプル #04 の続き。 TargetFrameworkVersion: v4.7.2
XAML 諸島は、WPF のウィンドウに、UWP のコントロールを配置する。このサンプルでは、カメラとキャプチャ Windows.UI.Xaml.Controls.CaptureElement
クラスと MessageDialog
クラスを使っている。
2023年3月現在, .NET 6 では XAML 諸島は使えない。.NET Core 3.1 のサポート期間も2022年12月で終了した。 .NET Framework 4.7 を使え。ひどい。
11_DynamicColumnsInDataGrid/
<DataGrid>
の「列」を動的に追加する。この目的のときだけ, 列指向である DataTable
クラスを使う。
DataTable
クラスは、まあまあ罠が多い
14_Notepad-wpf/
MVC モデル, Undo-Redo の実装。添付ビヘイビア。
15_weak-listener/
WPF は, view と view model は 1:1 になっていて、寿命も同じ。アプリケィションは通常 MVC モデルで作り, WPF では document (model) の変更を view model で察知する。View & view model のほうが document よりも寿命が短い。
INotifyPropertyChanged
インタフェイスの PropertyChanged
イベントはターゲット (listener) を強参照で保持するため, view を閉じたときにイベントハンドラを remove しなければ, メモリリークする。
このサンプルでは, view model 側のイベントハンドラを document に登録するときに, Mediator デザインパタンの PropertyChangedEventManager
を挟む. イベントハンドラ側が弱参照になって、view を単に破壊してもよくなる。
10_data-protect/
分離ストレージ (Isolated Storage) は、どの程度データが保護されるのか?
結果:
何ですと!
Data Protection API (DPAPI) を組み合わせる:
12_ReadExcel/
Excel ファイルを読み込み、表に表示する。表示にウィンドウを使っているが、主眼はファイルを読み込むところ。
16_aop-auto-inotifypropertychanged/
アスペクト指向プログラミング (AOP). TargetFramework: net6.0
いちいち INotifyPropertyChanged
(INPC) インタフェイスを実装するようにクラスを書くのは、非常に面倒くさい。オブジェクトのプロパティに値を代入するだけで自動的に notify するようにする。
次のクラスが実装例。このクラスで, INotifyPropertyChanged
(INPC) はどこにも出てこない。
INPC にキャストして使う:
ちゃんとしたライブラリでは, C# Attributes をクラスに付けて、オブジェクトの生成すら隠蔽できる。例えば, MVVM Toolkit v8 では次のようになる。See .NET用 MVVM Toolkit v8でMVVMコードを短く
余談だが, MVVM Light の後継が Microsoft MVVM Toolkit, 名前が変わって CommunityToolkit.Mvvm パッケージ. このパッケージは .NET Community Toolkit プロジェクトの一部。ヤヤコシイことに, 別系統の Windows Community Toolkit があって, そちらは UWP (WinUI2), WindowsAppSDK/WinUI3, Uno Platform 用。ヤヤコシや
EF Core + SQLite サンプルや, EF6 サンプル。
06_SqliteMigrationSample/
ローカルでデータ保存に SQLite を使うサンプル。.NET Framework 4.7 と Entity Framework Core (EF Core) 3.1 の組み合わせ。
08_sqlserver-ef6-wpf-datagrid/
Entity Framework 6 (EF6). Microsoft SQL Server に接続する。 TargetFrameworkVersion: v4.7.2
13_AdventureWorks.WPF/
AdventureWorks LT のサンプル。 TargetFrameworkVersion: v4.7.2