これらのユーザーコントロールが1回しか使用されない場合でも、ユーザーコントロールを使用してWPFフォームを構造化することは良い習慣ですか?


8

私はMVVMを使用してWPFアプリケーションを開発していて、最善の方法を学んでいます。

セレクター付きのWPFフォーム、検索フィールド付きの2つのリスト、およびその他の要素があります。現在、すべてが1つの形式になっており、機能します。しかし、今ではそのフォームのVMは800行を超えており、まだ完成していません。

このフォームとコードをよりよく構成したいと思います。リージョン、部分クラスを含むファイル、ユーザーコントロールについて考えました。ユーザーコントロールは、いくつかのコントロールとロジックをカプセル化しているため、最適だと思います。ユーザーコントロールを使用すると、そのウィンドウとVMのコード量が大幅に削減されます。

これを正しく行うために、「Pro WPF 4.5 In C#4th Edition」という本の第18章-カスタム要素とColorPickerUserControlサンプルに取り組みます。サンプルは、3つのスライダーを備えたカラーピッカーに関するもので、150行のコードが含まれています。

私はそれがどのように機能するか理解していると思いますが、そのサンプルのように機能が非常に制限されていても、ユーザーコントロールを作成するのは大変な作業だと思います。これらのコントロールを数回使用する場合、これを行うのが理にかなっていることを理解しています。しかし、コントロールを1回だけ使用し、これをフォームの構造化のみに使用する場合、これはほとんど利益を得るために多くの作業と思われます。

私の質問は次のとおりです。これらのユーザーコントロールが1回だけ使用される場合でも、ユーザーコントロールを使用してフォームを構造化することは良い習慣ですか?そうでない場合、より良い代替手段はありますか?

編集(読む必要はありませんが、詳細情報のみ):原則について学びたかったので、これまで詳細は書きませんでしたが、26の興味深い答えの17を読んだ後、ここにいくつかの詳細があります:このフォームは、音楽のタイトルを選択するためのものです。

  • グループA:(可能なユーザーコントロールA)は、アーティストまたはアルバムによる選択、ビデオの有無にかかわらず、おそらく発行年など、選択のタイプについてです。

  • グループB:このリストには、Aの基準に従ってフィルタリングされたアーティスト名が含まれています。ユーザーはリストをフィルタリングできます。つまり、「トップ」を含むアーティスト名のみを表示できます。

  • グループC:このリストには、Aの基準(オーディオまたはビデオ)を使用して、Bで選択したアーティストのタイトルが表示されます。Bと同様にフィルタリングできます。つまり、「あなた」を含むタイトルのみです。

ほとんどのロジックはVM(フォームのDataContext)で発生します。AとBのリストはデータベースからのものです。リストはフィルタリングされ、プレゼンテーション用に準備されます(つまり、同じ名前であるが異なるアルバムにある複数のタイトル)。ユーザーは、ダブルクリックしてCリストのタイトルを選択するか、別のWPFフォームにドラッグアンドドロップします。

必要なもの:簡単に修正できるように、読み取り可能なコードが必要です。別のフィルターを追加する場合、つまり女性アーティストのみを表示する場合は、ユーザーコントロールAに移動して、男性および/または女性アーティストのチェックボックスを追加するだけでよいとしましょう。

現在の形式のXAMLは問題なく、適切に構造化されています。ただし、VMには上記すべてのコードが含まれています。コンストラクター、コマンドセクション、プロパティ、バッキングフィールドにいくつかあります。私は今でも物事を見つけることができますが、コードがより構造化されていればもっと良いと思います。これがユーザーコントロールについて考える理由です。

MVVMの背後にあるロジックは非常に理にかなっていると思うので、MVVMをフォローしようとしています。しかし、私は理論的な実践の熱狂的な信者ではありません。つまり、VMで5行のCodeBehindまたは50行で何かを実行できる場合、CodeBehindで実行する可能性があります。私の質問は、WPFで構造化フォームを作成する方法の原則についてです。上記で説明したフォームは良い例ですが、答えはこの1つのフォームに集中するのではなく、WPFフォームを構成する方法、つまりユーザーコントロールを使用する(または使用しない)方法に集中する必要があります。

ユーザーコントロールが多くの作業を必要とする理由について:依存関係プロパティ、ルーティングイベントなどがあります。これはすべて、バッキングフィールドとINotifyを使用した「通常の」プロパティよりもはるかに複雑に思えます。しかし、依存関係プロパティ、ルーティングイベントなどに慣れる必要があるだけかもしれません。


ユーザーコントロールを作成するのが大変だと思う理由については、少し戸惑いました。最も単純な形式では、UserControlは単なるコンテナーです。次のように作成します<UserControl> </UserControl>。それでおしまい。
ロバートハーベイ

編集に関して:ユーザーコントロールは、依存関係プロパティ、ルーティングイベントなど、それらを配置することにした場合にのみ存在します。 これらは必須ではありません。
ロバートハーベイ

@RobertHarvey:はい、理解しています。しかし、双方向バインディングによる「完全な機能」、ユーザーコントロールの何かが変更された場合などにメインフォームの何かをトリガーすることなどが必要であるようです。私が上記で言及した本のサンプルは、それらがしばしば(常にではない)どれほど必要であるかを示していると思います。
エドガー

ユーザーコントロールを使用せずに、これらすべてを実行する必要はありませんか?
ロバートハーヴェイ

1
また、ViewModelが多くのことをしているようにも聞こえません。結果のリストのソートとフィルタリングは、ViewModelにとってかなり小さなタスクです。多分問題は、VMが何をしているではなくそれがどのように書かれているです。おそらく、コードサイズを削減するために使用できるいくつかのC#機能があるでしょう。または、VMをリファクタリングしてサイズを縮小することもできます。
26の17 17

回答:


7

もちろん。単一のタスクを実行するために、クラスに関係の分離を適用して、クラスをそれぞれ独自に配置するのと同じように、良いアイデアです。そのクラスのインスタンスは1つしか持てませんが、重要ではありません。最適化はプログラムのパフォーマンスの観点ではなく、組織とプログラム全体の「健康」の観点からです。

リージョンに配置されたとしても、ある日プログラムに戻って、数百ページのコードをスクロールする必要がないことを望んでいます(多くのコードを持つクラスのリージョンを使用することは、豚に口紅を付けるようなものです)仕方)。いつか別の場所で使用することを決定した場合でも、多くの問題なしに、優雅に使用できます。

親フォームへのアクセスをユーザーに制御させようとしないでください。この方法で行う場合は、イベントを使用して、親フォームをサブスクライバーとして、親に情報を伝えます。


また、カスタムコントロールを作成するときに、それが担当するプレゼンテーションロジックの一部をカプセル化できます。これにより、正しく実行すると、含まれているコントロールのプレゼンテーションロジックが単純になります。
FilipMilovanović18年

「絶対にそう」は、ユーザーコントロールを作成するための労力がOPの説明と同じくらい高い場合は、IMHOは適切な答えではありません。
Doc Brown、

1
VIewModelには、一連のユーザーインターフェイスコントロールのユーザーインターフェイスロジックを調整するという単一の問題があります。これらを分割することは困難で、多くの場合意味がありません。

2
@DocBrownこの質問は、一般的な実践に関する意見を求めています。だからニールの答えは公平で正直な意見だと思います。絶対的な答えはありませんが、どこかから始めることをお勧めします。私は私がそれをコード化するために支払われていた場合、私はそれを正しい方法で行います(ニールの推薦)。また、将来のプロジェクトでコントロールを再利用したい場合は、これが実際に役立ちます。しかし、私が遊んだり、自分で何かを作りたいだけの場合、私はすでに洗濯物に遅れを取っているので、それをより迅速に行います。
クリストファー

1
「絶対はい」は誤りです。正解は「場合によります」です。ビュー/ VMを複数のビュー/ VMに分割すると、コストと複雑さが増します。利益はコストを上回る必要があります。
18の26

4

これは実際のコードを見ずに答えるのは本当に難しい質問です。また、用語を少し混ぜています。ユーザーコントロールは、ViewModelとの1対1のマッピングではありません。

ユーザーコントロールには特定の目的があります。これらは、1つの単位として一緒に使用される複数のUI要素の構成です。ユーザーコントロールは、ビューのサブセクションです。これは、Viewがバインドされているロジックを含むViewModelとは大きく異なります。

XAMLを複数のユーザーコントロールに分割して、すべてが単一のViewModelによって駆動されるようにするのは理にかなっています。XAMLとC#のコードを複数のView-VMペアに分割することは意味があるかもしれません。多分それをあなたが今持っているままにしておくことは理にかなっています。問題のコードを見ずに伝えることは不可能です。

ここでの最終目標は何ですか?コードのサイズが実際の苦痛を引き起こしているのですか、それとも単に理論上の慣習に従うためですか?

XAMLビューのサイズまたはC#ViewModelのサイズを縮小しようとしていますか?これらは、WPF MVVMの世界では2つの非常に異なるタスクです。

800行は、なんらかの複雑さを持つUIをサポートするVMにとってはそれほど大きくありません。VMを分割すると、解決できない問題が発生することがよくあります。ViewModelは、「この他のリストが空のときにこの機能を無効にする」などの決定を行います。このような意思決定を複数のコンポーネントに分割しようとしても、多くの場合意味がなく、コードが複雑になります。

これで、VMで実行している作業がViewModelロジックとは関係なく、簡単に独自のクラスに分割できる可能性があります。これにより、コード全体の複雑さを増すことなく、ViewModelのサイズを削減できます。

それは、「それは場合によって異なり、問題のコードを見ないと分からない」という非常に長い時間のかかる方法だったと思います。


ご回答有難うございます。複数のView-VMペアを持つことについて読んだことはありません-それは興味深いアイデアのように聞こえます。残りのために私はそれを私の質問に追加しました。
エドガー

この複数のView-VMペアのViewとは(a UserControl/a Grid/a Page ??)
コードネームJack

0

アプリについて何も知らない私が姓フィールドの上に新しいフィールドを追加するか、いくつかのフィールドの順序を変更しなければならなかった場合...私はそれが簡単か、気が遠くなるでしょうか?

コンパイラーは間違ったリージョンに何かを置き忘れたかどうかをチェックしないため、リージョンを信頼しません

あなたが作成したものの上に人々が簡単に構築できるようにするために、ソフトウェアを開発する必要があります。


WPFでフォームを作成したことがありますか?はいの場合は、フォームのXAML部分で記述したことを行い、コードビハインドやVMでは行わないことを知っておく必要があります。またはあなたの質問に答えるために:はい、それはとても簡単でしょう。
エドガー

@エドガー私のせい。あなたはビジュアルコンポーネントとユーザーコントロールについて話しました、そしてそれがすべてだと思いました。すべてのビジュアルがビューにあり、すべてのビジネスロジックがモデルにある場合、VMが長くなる心配はありません。
A Bravo Dev
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.