====== WPF開発 ====== ===== WPFとは ===== Windows Presentation Foundation(WPF)は、マイクロソフトが開発したグラフィカルユーザーインターフェース(GUI)を開発するためのグラフィックスサブシステムの名称である。.NET Framework 3.0に含まれてリリースされた。\\ WPFでは、XAML(Extensible Application Markup Language)と呼ばれるXMLベースの描画用マークアップ言語に対応している。従来のビットマップグラフィックスの他にベクタグラフィックスを扱うことが可能であり、3次元グラフィックスや動画なども容易に扱えるようになった。これらのユーザーインターフェースは、テキストやドキュメントも含めて、統一的なAPIを用いて開発することができる。 WPFの最大の売りは多彩なUIによるユーザー体験の豊かさである。 * [[https://techinfoofmicrosofttech.osscons.jp/index.php?WPF|WPF - マイクロソフト系技術情報 Wiki]] * [[http://www.kanazawa-net.ne.jp/~pmansato/wpf/wpf_base.htm|WPF の基礎知識]] ===== Windows Formsとの違い ===== ==== メリット ==== Windows Formsと比べてWPFのいいところは可変のレイアウトが作りやすいこと。\\ また、色々なデバイスでできるだけレイアウトが崩れないようにフォントサイズを含めたすべてのサイズ指定で論理ピクセル座標が標準になっている。参照:[[http://d.hatena.ne.jp/Yamaki/20091215/1260947088|デバイス非依存ピクセル(DIU)について]] Windows Forms では主に UI 要素に対してプロパティーを通じて個別に外観設定を行いますが、WPF では異なるスタイリングに対するアプローチをとっています。\\ WPF では強力なスタイルモデルを提供しており、基本的には Web 開発で用いられる CSS のような手法でスタイリングが行われます。これにより一元的な外観管理を行いやすくなります。UI とロジック部分が分離されるのでアプリケーション開発者とデザイナの分業が可能です。デザイン部分の再利用性も高まり、仕様変更にも柔軟に対応すること ができます。 * [[https://yryr.me/programming/csharp/forms-app-wpf-advantage.html|FormsアプリにないWPFの長所]] * [[http://blogs.jp.infragistics.com/blogs/jpdevsupport/archive/2013/05/21/winforms-wpf.aspx|Windows Forms と WPF でのアプローチの違い]] * [[http://d.hatena.ne.jp/Yamaki/20091215/1260947088|WPFにおけるフォントサイズの指定]] * [[http://grabacr.net/archives/1105|Visual Studio 2012 のような光るウィンドウを作る (再)、そして WPF での高 DPI 対応]] * [[http://d.hatena.ne.jp/hilapon/20160621/1466501984|高DPI環境における Windows Forms アプリ終了のお知らせ]] ==== デメリット ==== 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へのアップデートが必要。 * [[http://aroundthedistance.hatenadiary.jp/entry/2016/05/13/021751|業務系アプリでWPFを使うメリットがなかった件]] * [[https://teratail.com/questions/77077|新規開発ソフトのWindowsForms、WPF、UWPの選択について]] * [[https://www.infoq.com/jp/news/2017/05/net47|WPFとWinFormsを改善した .NET Framework 4.7]] * [[https://qiita.com/felis_silv/items/efee4b1a397b0b95100a|Windows Formsアプリケーションの高DPI対応]] * [[https://techinfoofmicrosofttech.osscons.jp/index.php?Windows%20Form%20vs%20WPF|Windows Form vs WPF]]   ===== Tips ===== ==== Wrap対応のLabel ==== 通常のLabelコントロールは、自動改行のwrapに対応していません。下記コードで対応する。 * [[https://stackoverflow.com/questions/5013067/how-can-i-wrap-text-in-a-label-using-wpf|How can I wrap text in a label using WPF?]] * [[http://final.hateblo.jp/entry/2015/11/03/215644|WPFでTextBlockの高さを文字数に合わせて自動で調整する。]] ==== TextBlockとLabelの違い ==== TextBlockは文字列のみを表示することができます。一方でLabelの方はContentに与えられる全てのオブジェクトに対応することができます。\\ [[http://neareal.net/index.php?Programming%2F.NetFramework%2FWPF%2FTextBlock%20TextBox%20Label|TextBlockとLabelの違い]] ==== 一つの文字列に複数のデータをバインディングしたい場合 ==== マルチバインディングを使う。\\ [[https://qiita.com/koara-local/items/815eb5146b3ddc48a8c3|[WPF] XAMLでの文字列のフォーマット指定とバインディング]] バインディングするデータが最初に来る場合は、頭に {} を付ける必要があります。(属性値のBindingなどではなく文字として中括弧がつかいたいため) ==== スクロールバーのサイズ取得 ==== ListViewのスクロールバーのサイズを取得する。\\ [[http://pieceofnostalgy.blogspot.jp/2014/04/wpf-listview.html|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; ==== タスクトレイ常駐アプリ ==== [[https://garafu.blogspot.jp/2015/06/dev-tasktray-residentapplication.html|C# WPFでタスクトレイ常駐アプリの開発]] ==== ファイル監視で画面表示 ==== ファイル監視イベントで画面表示処理を呼び出すと「呼び出しスレッドは、多数の UI コンポーネントが必要としているため、STA である必要があります。」が発生する。\\ [[http://code.i-harness.com/ja/q/238d7a|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 の呼び出しを行うことはできません。」 フォームインスタンスを再利用するとでる。 * 他のフォームをnewする * ShowModalで開く * そのフォームを閉じる * new済みなので、再度ShowModalで開く 対応方法 * [[https://qiita.com/7of9/items/b6cc4c7a5d407b01ffc9|Visual Studio / WPF > Form > 閉じたウィンドウを再度ShowModal()したとき > Error:System.InvalidOperationException: 'Window が閉じた後で、Visibility の設定や、Show、ShowDialog、およびWindowInteropHelper.EnsureHandl の呼び出しを行うことはできません。 > 対処]] * [[https://stackoverflow.com/questions/3568233/wpf-cannot-reuse-window-after-it-has-been-closed|WPF: Cannot reuse window after it has been closed]] private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { e.Cancel = true; this.Visibility = Visibility.Hidden; } ==== Shownイベント ==== WPFにはWindowが最初に表示されたときのShownイベントが無いので、代わりにContentRenderedイベントを利用する。\\ [[https://qiita.com/tricogimmick/items/79e85baa1e99eec840d8|WPF Windowが最初に表示されたときに処理を行いたい]] ==== 表示文字幅の取得 ==== 画面に表示される文字の幅を取得する。\\ [[http://blogs.wankuma.com/hirom/archive/2009/08/05/179828.aspx|WPFで表示文字幅の取得を行う。]] Typeface typeface = new Typeface(txtTest.FontFamily, txtTest.FontStyle, txtTest.FontWeight, txtTest.FontStretch); double len = MeasureString("テスト", txtTest.FontSize, typeface).Width; /// /// 表示文字幅を取得する /// /// /// /// /// 表示文字サイズ 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); } ==== Buttonのクリックイベントを発生させる ==== WPFには、Windows FormにあったPerformClickメソッドが存在しない。\\ IInvokeProviderインターフェースを利用するには、参照の追加の参照マネージャーのアセンブリから「UIAutomationProvider.dll」を参照する。\\ [[http://blog.xin9le.net/entry/2013/10/27/195614|ボタンをプログラム側からクリックする]]\\ [[http://dobon.net/vb/dotnet/control/performclick.html|Buttonのクリックイベントを発生させる]] ==== 最大化を禁止させる ==== //最小化ボタンは有効、最大化ボタンは表示されてるけど、無効。 this.ResizeMode = ResizeMode.CanMinimize; [[http://d.hatena.ne.jp/tako222/20090827/1251379855|WPFでGUIアプリケーションを作成する際のメモ その3]] ==== Bindingのソースが更新されない ==== ViewModelにINotifyPropertyChangedインターフェイスを実装する必要がある。\\ * [[http://blog.okazuki.jp/entry/2014/09/15/201110|WPF4.5入門 その55 「Binding その1」]] * [[http://blog.okazuki.jp/entry/20091214/1260803280|INotifyPropertyChangedのいけてる実装]] * [[http://var.blog.jp/archives/67585928.html|Binding Source が更新されない]] INotifyPropertyChangedを実装はイケてないので、ReactivePropertyを使用する。\\ NuGetから「ReactiveProperty 3.6.0」で入手する。 * [[https://qiita.com/ledsun/items/6f4ef754e5ae2507e531|INotifyPropertyChanged実装のありえない面倒くささと、ReactivePropertyの信じられない素晴らしさ]] * [[http://blog.okazuki.jp/entry/2015/12/05/221154|MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー]] ==== ListViewの選択背景色を変更する ==== === XAMLでの変更方法 === [[https://stackoverflow.com/questions/4246795/change-selection-color-of-wpf-listviewitem|Change selection-color of WPF ListViewItem]] === コードによる変更方法 === [[https://www.codeproject.com/Articles/29699/WPF-How-to-create-Styles-in-code-and-magical-Conte|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; ==== メモ ==== * [[https://stackoverflow.com/questions/632519/how-can-i-hide-the-header-of-a-listview-wpf|How can I hide the header of a listview WPF?]] * [[http://pieceofnostalgy.blogspot.jp/2014/04/wpf-listview.html|wpf : ListViewのある列の幅を自動でいっぱいに広げその他の列幅は固定]] * [[https://stackoverflow.com/questions/4725352/wpf-listview-with-gridviewcolumn-and-datatemplate|WPF ListView with GridViewColumn and DataTemplate]] * [[https://stackoverflow.com/questions/2834971/listview-column-auto-sizing|ListView column auto sizing]] * [[http://windowspresentationfoundationinfo.blogspot.jp/2014/09/wpf-listview.html|Windows Presentation Foundation (WPF)]] * [[http://blog.okazuki.jp/entry/20130218/1358172834|WPF4.5入門 その23 「DataGridコントロール その1」]] * [[http://getbget.seesaa.net/article/436822830.html|WPF - DataGrid のデータ表示部分の背景色を変える]] * [[http://hogetan.blog24.fc2.com/blog-entry-7.html|WPFでリサイズ可能な枠なしウィンドウを作成する]] * [[http://d.hatena.ne.jp/CoMo/20110421/1303394273|WPFのレイアウトのTips]] * [[http://sourcechord.hatenablog.com/entry/20131028/1382978042|アプリの多重起動を防止する]]