14407


おはようございます。

表題の件について皆様はどのようにされていますでしょうか？

Windows FormアプリケーションをVisualStudio2010で作成しています。  
GUIでインターフェースが作成できるのは便利ですがフォームをクリックしたりするとフォームのコード（例：Form1.vb）にイベントハンドラーが自動生成されてしまいます。

自分のような初心者にはありがたい機能なのですが度が過ぎるとフォームのコードが多くなりすぎて可読性が低下する原因になると思います。

このような時、皆様はどのような対応をされておられるのでしょうか？

自分の場合はフォーム（Form1.vb）に対して対になるロジッククラス（Form1_logic.vb）を作成し、ロジッククラスのコンストラクタとしてフォームそのものを引き渡し、フォームに対する操作の処理はロジッククラスに書くようにしています。

こうすれば元のフォームにはロジッククラスのメソッドに対する呼び出しだけですみますがこのやり方で何か不都合が発生しますでしょうか？

他にスマートな実装方法などございましたら紹介いただけますでしょうか。

よろしくお願いします。


CC BY-SA 3.0
2015-08-14T01:25:56.207
14404
2015-08-14T04:28:43.737
10606
question
.net visual-studio winforms
Windows Formアプリケーションでのロジック部とユーザーインターフェース部の分離について


現状では

[code]

    Class Form1
    
        Sub New
            logic = New Form1_Logic(me)
        End Sub
    
        Sub Button1_Click()
            logic.OnButton1Click()
        End Sub
    
    End Class
    
[/code]

というイメージであるということですよね？これは一般的な設計ポリシーの評価では

  * Form1とForm1_logicが相互に依存している
  * Form1_logicで扱うデータがForm1そのもので抽象化がされていない

という2点で難があるかと思います。

上記はもちろんクラス分割を改善するのがベストですが、この手の設計方針には多分に個人の趣味が含まれるので反対にForm1をまったく分割せずに可読性を上げるテクニックをいくつか紹介します。

# Regionディレクティブ

[code]

    #Region "リージョンの名前"
    
    
    #End Region
    
[/code]

のような記述を追加することでコードの一部を折りたたむことができ、これでメソッドを分類すればコードが把握しやすくなります。

# パーシャルクラス

Form1.hoge.vbのようなファイルを追加し、

[code]

    Partial Class Form1
    End Class
    
[/code]

と`Partial`修飾子を指定すればこのファイルはForm1.vbおよびForm1.Designer.vbと併せて1つのクラスとなり、関連している処理を別ファイルにまとめることができます。

* * *

※これらは設計を変更しない小手先の手法ですので、本質的にはデータバインドなどを含めた設計の改善が重要です。


CC BY-SA 3.0
2015-08-14T02:25:54.703
14407
2015-08-14T02:25:54.703
2020-06-17T08:14:45.997
-1
5750
14404
answer


クラス分割や抽象化は、ロジックに着目しがちですが、  
画面（Windowsフォーム）自体にも適用できます。

例えばヘッダ部・フッダ部、ＯＫ・キャンセル・閉じるボタン、時刻表示など、  
複数画面で汎用的に使えるコントロールやイベント（つまり共通の画面レイアウト）を  
定義した抽象フォームを作成しておきます。  
その抽象フォームを継承したフォームで個々の画面を作成する、といった具合です。  
ソースが減るだけでなく、デザイナ上での管理も楽になるかと思います。  
（継承部分のコントロールはロック状態で、触っても勝手にイベント等は作成されない）

アプリケーションによって向き不向きはあると思いますが、  
イベントの記述のみ可読性が落ちるほど長くなるなるような  
多コントロール多機能フォームということでしたら、  
こういった手法も1つの解法になるかなと思います。

[code]

    ''' <summary>抽象フォーム</summary>
    Public Class FromBase
        '全画面共通の閉じるボタン
        Private Sub btn_Click(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles btn.Click
            Me.ButtonClick(e) '★
            Me.Close()
        End Sub
    
        '★もし共通のイベントに継承先で独自処理を追加したいならば、抜け道を用意しておく
        Protected Overridable Sub ButtonClick(ByVal e As System.EventArgs)
        End Sub
    End Class
    
    ''' <summary>継承フォーム</summary>
    Public Class FromA
        Inherits FromBase
    
        '共通でない独自のイベント・処理を記述していく
    
        '★
        Protected Overrides Sub ButtonClick(ByVal e As System.EventArgs)
            Commit()
            MyBase.ButtonClick(e)
        End Sub
    End Class
    
[/code]


CC BY-SA 3.0
2015-08-14T03:48:07.687
14410
2015-08-14T03:53:50.310
2015-08-14T03:53:50.310
5133
5133
14404
answer


確実にドメインを分岐したい場合、Formを使用すべきではありません。  
WPFに移行を検討し、MVVMパターンを採用すべきです。

フォームアプリケーションでも、多少ながらもデータバインディングを使用できるので、MVVMのようなパターンを採用することは、可能です。

ですが、WPFに比べ、貧弱なものであり、下準備がある程度必要になったりしますので可能であれば、WPFに移行したほうがスムーズです。

いくつかのコントロールは、DataBindingsプロパティを公開しており、プロパティのデータバインディングに対応しています。

<http://devlights.hatenablog.com/entry/20070413/p1>

ToolStripMenuItemなど、DataBindingsプロパティを公開しない場合、継承したクラスにIBindableComponentインターフェースを実装します。

<http://d.hatena.ne.jp/vegatech/20070911/1189507701>

DataGridViewなどのリスト系のコントロールでもデータバインディング可能です。

<http://www.atmarkit.co.jp/fdotnet/chushin/introwinform_06/introwinform_06_01.html>

* * *

  * フォームの場合、PropertyChangedイベントは、UIスレッド上で発生させる必要がある。
  * プロパティ名を文字列で指定するよりは、nameofを使用すべきです。※ VS2015
  * 何度も言いますが分離を考えるならWPFに以降したほうが確実にスムーズでしょう。


CC BY-SA 3.0
2015-08-14T04:28:43.737
14411
2015-08-14T04:28:43.737
2207
14404
answer