読者です 読者をやめる 読者になる 読者になる

Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

Windowsフォーム開発で思ったこと

世の中はWPFらしいんですけど、WPF覚えるよりも慣れたWindowsフォームのほうが圧倒的に開発速度が速かったし別に動かないワケじゃないから、Windowsフォームでここ2ヶ月ぐらいアプリを作っています。思ったことをまとめておきます。随時加筆修正予定。

画面遷移

1つのWindowsフォームを用意して、そこにパネル領域を用意する。で、そのパネルに対して、自分で作ったUserControlをAdd/Removeする作りをネットで見かけて「これで十分だなー」と思い採用させてもらいました。UserControlを作る際にbasePanelという空のユーザーコントロールを僕は用意して、各画面で共通するメソッドやプロパティをそこに集約させています。で、ユーザーコントロールを追加したあと、ソースコードの継承先をUserControlからBasePanelにする、と。なんか「似たようなことやってるけど、微妙にI/Fのみが違う」ことが多かったので、その辺の処理を共通化することが出来ました。

データグリッド関係

業務系と言えばグリッドですよね。小画面出すときもグリッド、入力するときもグリッドみたいな。最初はデフォルトのdatagridviewをドラッグ&ドロップしてたんですが、すぐに破綻しました!圧倒的・・・Coppy&Paste・・・!流石にダメ・・・!猛省・・・!流石の僕も猛省・・・!

というわけで、コードからDataGridViewを生成したほうが100倍メンテが楽。コンポーネント化しましょう。結局BaseDataGridViewというDataGridViewを継承したクラスを用意して、カラム定義やサイズ位置の指定などをこいつのサブクラスで行うような設計にした。これもGoodだった。

BaseDatagridViewにはフォーカス制御、入力制御、セル毎のイベントハンドライベントハンドラのコールバックなどを定義しておいた。デフォルトの処理はスーパクラスが行い、なんかちょいとカスタマイズしたい時はvirtualで定義したメソッドを用意してオーバーライド。例えば品番を入力されたら品番存在チェックをかけにいく所までは同じだけど、この業務の時は残在庫を確認しないといけない場合などに、とても有効。「イベントの発火までは一緒だけど、着地点が微妙に違う」ことが結構多く、このやり方はかなり重宝した。もちろん各画面からはBaseDataGridView b = new OrderDataGridView()みたいな感じにして、初期化。殆どの場合、サブクラスにはデータグリッドのカラム定義とそのスタイル定義を実装するだけで終わった。

グリッドから親画面に処理を渡すこともあったので、そのメソッドは全てBasePanelに定義した。ただ、困ったことにGUIインスタンスは各画面でないと拾えなかったので、グリッドでF2を押したら親画面のどこそこにフォーカスを移す場合はbasePanelにvirtualなメソッドを定義して、サブクラスでその処理を継承して対応した。修正は瞬殺だし処理内容もたいした内容じゃないにせよ、多少なりともこのやり方だとコピペが量産された。うまい方法ないかな・・・。

あとDataSet.ReadXmlを結構使うので、データセットの中身をダンプするメソッドを用意した。結構重宝した。phpでいうvar_dumpみたいなヤツ。あとはブレークポイント使えばおk。

子画面関係

子画面もChildFormみたいなヤツだけ1個用意して、適宜UserControlをAddする仕組みにした。顧客一覧表示と品番一覧表示の違いは、データグリッドの構成の違いぐらいしかない・・・!ほんなら、UIKitのinitWithXXみたいな感じのメソッドをUserControlに用意して、親画面から適した初期化メソッドを叩けばそれでよいと思いました。子画面には親画面のBasePanelのインスタンスだけを用意させた。各画面がbasePanelを継承しているので、basePanel.setXXData()みたいなメソッドを用意しておけば、basePanelにあるプロパティに値が入ってそれを各画面がよしなにやればいいだけ。

ページング

DataGridViewでページングを行うために、Paginatorというクラスを作ってページング専用の処理をそっちに任せるようにした。どうせページングなんて、「検索条件の覚え込み」と「検索結果件数」と「ページ数」をはじき出せば、あとはlimit offsetするだけだし。恐らく1000件ぐらいなら一気に表示してもいいかもしれないんだろうけど、「→」と「←」のキーでページングできた方が楽そうだったからそうした。

あと、DataTableはHashtable#Containsに相当するメソッドがないのでカラムの存在チェックができなくて一瞬困ったけど、Columnsを回してcolumeNameでハンドリングしたらそれなりにやりたいことができたのでまぁいいかと思った。

例外処理

全部集約させたかったので、こちらを参考にした。各画面にtry~catch書くとかないわ。全部スローしてどこかで例外発生したらそいつをつかまえる仕組みにしないと。

.Net Framework 例外処理の基本 集約例外ハンドラ(Windows フォーム) C# でのサンプル | Scribbled Records

C#って楽

.NETFrameworkが楽にさせてくれているのだろうけど、静的言語と動的言語の良いとこ取りをしている卑怯な言語だなと感じた。けしからん、もっとやれ。