Windows Presentation Foundation(WPF)は、マイクロソフトが開発したグラフィカルユーザーインターフェース(GUI)を開発するためのグラフィックスサブシステムの名称である。.NET Framework 3.0に含まれてリリースされた。
WPFでは、XAML(Extensible Application Markup Language)と呼ばれるXMLベースの描画用マークアップ言語に対応している。従来のビットマップグラフィックスの他にベクタグラフィックスを扱うことが可能であり、3次元グラフィックスや動画なども容易に扱えるようになった。これらのユーザーインターフェースは、テキストやドキュメントも含めて、統一的なAPIを用いて開発することができる。
WPFの最大の売りは多彩なUIによるユーザー体験の豊かさである。
Windows Formsと比べてWPFのいいところは可変のレイアウトが作りやすいこと。
また、色々なデバイスでできるだけレイアウトが崩れないようにフォントサイズを含めたすべてのサイズ指定で論理ピクセル座標が標準になっている。参照:デバイス非依存ピクセル(DIU)について
Windows Forms では主に UI 要素に対してプロパティーを通じて個別に外観設定を行いますが、WPF では異なるスタイリングに対するアプローチをとっています。
WPF では強力なスタイルモデルを提供しており、基本的には Web 開発で用いられる CSS のような手法でスタイリングが行われます。これにより一元的な外観管理を行いやすくなります。UI とロジック部分が分離されるのでアプリケーション開発者とデザイナの分業が可能です。デザイン部分の再利用性も高まり、仕様変更にも柔軟に対応すること ができます。
WinFormに使い慣れている人からするとWPF+XAMLの習得コストが高い。
.NET Framework 4.7では、WPFの特徴でもある高DPIサポートがWindows Formsアプリケーションに適用されるようになった。但し、.NET Framework 4.7を利用してアプリケーションを開発するには、Windows 10 バージョン1703や「Visual Studio 2017」でv15.0からv15.1へのアップデートが必要。
通常のLabelコントロールは、自動改行のwrapに対応していません。下記コードで対応する。
<Label x:Name="lblHeader" Grid.Row="0" FontSize="32" > <AccessText TextWrapping="Wrap" Text="手直し品です。ご注意ください。12345678901234567890"/> </Label>
TextBlockは文字列のみを表示することができます。一方でLabelの方はContentに与えられる全てのオブジェクトに対応することができます。
TextBlockとLabelの違い
マルチバインディングを使う。
[WPF] XAMLでの文字列のフォーマット指定とバインディング
<TextBlock> <TextBlock.Text> <MultiBinding StringFormat="{}First {0} : Second {1}"> <Binding Path="FirstValue"/> <Binding Path="SecondValue"/> </MultiBinding> </TextBlock.Text> </TextBlock>
バインディングするデータが最初に来る場合は、頭に {} を付ける必要があります。(属性値のBindingなどではなく文字として中括弧がつかいたいため)
ListViewのスクロールバーのサイズを取得する。
wpf : ListViewのある列の幅を自動でいっぱいに広げその他の列幅は固定
var listBoxChrome = VisualTreeHelper.GetChild(listView, 0) as FrameworkElement; var scrollViewer = VisualTreeHelper.GetChild(listBoxChrome, 0) as ScrollViewer; var scrollBar = scrollViewer.Template.FindName("PART_VerticalScrollBar", scrollViewer) as ScrollBar; var w = scrollBar.ActualWidth;
ファイル監視イベントで画面表示処理を呼び出すと「呼び出しスレッドは、多数の UI コンポーネントが必要としているため、STA である必要があります。」が発生する。
wpf - 多くのUIコンポーネントがこれを必要とするため、呼び出しスレッドはSTAでなければなりません
UIスレッドで動作させために、下記内で画面表示処理を呼び出す。
Application.Current.Dispatcher.Invoke((Action)delegate
private void watcher_Changed(Object source, FileSystemEventArgs e) { switch (e.ChangeType) { case WatcherChangeTypes.Changed: case WatcherChangeTypes.Created: Application.Current.Dispatcher.Invoke((Action)delegate { MainWindowShow(); }); break; } }
例外エラー「'Window が閉じた後で、Visibility の設定や、Show、ShowDialog、およびWindowInteropHelper.EnsureHandl の呼び出しを行うことはできません。」
フォームインスタンスを再利用するとでる。
対応方法
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { e.Cancel = true; this.Visibility = Visibility.Hidden; }
WPFにはWindowが最初に表示されたときのShownイベントが無いので、代わりにContentRenderedイベントを利用する。
WPF Windowが最初に表示されたときに処理を行いたい
画面に表示される文字の幅を取得する。
WPFで表示文字幅の取得を行う。
Typeface typeface = new Typeface(txtTest.FontFamily, txtTest.FontStyle, txtTest.FontWeight, txtTest.FontStretch); double len = MeasureString("テスト", txtTest.FontSize, typeface).Width; /// <summary> /// 表示文字幅を取得する /// </summary> /// <param name="text"></param> /// <param name="fontSize"></param> /// <param name="typeFace"></param> /// <returns>表示文字サイズ</returns> private Size MeasureString(string text, double fontSize, Typeface typeface) { var ft = new FormattedText(text, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, fontSize, Brushes.White); return new Size(ft.Width, ft.Height); }
WPFには、Windows FormにあったPerformClickメソッドが存在しない。
IInvokeProviderインターフェースを利用するには、参照の追加の参照マネージャーのアセンブリから「UIAutomationProvider.dll」を参照する。
ボタンをプログラム側からクリックする
Buttonのクリックイベントを発生させる
//最小化ボタンは有効、最大化ボタンは表示されてるけど、無効。 this.ResizeMode = ResizeMode.CanMinimize;
ViewModelにINotifyPropertyChangedインターフェイスを実装する必要がある。
INotifyPropertyChangedを実装はイケてないので、ReactivePropertyを使用する。
NuGetから「ReactiveProperty 3.6.0」で入手する。
Change selection-color of WPF ListViewItem
<ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="midnightblue" /> </Trigger> </Style.Triggers> </Style> </ListView.ItemContainerStyle>
WPF: How to create Styles in code/and magical Content
// 選択時の背景色 Style styleListViewItem = new Style(typeof(ListViewItem)); Trigger triggerIsMouseOver = new Trigger { Property = ListViewItem.IsMouseOverProperty, Value = true }; triggerIsMouseOver.Setters.Add(new Setter(ListViewItem.BackgroundProperty, Brash.Gold)) SolidColorBrush(selectbackColor))); styleListViewItem.Triggers.Add(triggerIsMouseOver); lstRework.ItemContainerStyle = styleListViewItem;