高度に装飾された入力要素を多用するWPFアプリケーションを作成しています。装飾された要素の簡単な例は、フォーカスがない場合は読み取り専用のTextBlockのように見え、フォーカスを受け取るとTextBoxに変わるTextBoxです。また、変更された値がデータベースに保存されるときに、追加の視覚的なフィードバックが提供されます。問題は、これらの要素を多く含むビュー(たとえば、100)を表示するのが非常に遅く、アプリケーションが非常に応答しなくなることです。
このデコレータは、必要なすべての要素を含むUserControlとして実装されています(たとえば、フォーカスのないテキストを表示するTextBlockや、ビジーインジケーターの回転画像)。次に、このデコレータコントロールの子として入力要素を追加します。つまり、すべての追加要素に加えて、デコレータのビジュアルツリーにも入力要素が含まれます。XAMLでは、これは次のようになります。
<custom:Decorator Context="{Binding ValueHelper}" >
<TextBox Text="{Binding ValueHelper.Text}"/>
</custom:Decorator>
これにより、テキストボックス、日付ピッカー、コンボボックス、カスタム要素など、必要な入力要素を簡単に装飾できます。
ここで問題に戻ります。100個の装飾されたテキストボックスを含むビューがあり、そのビューに移動するとします。何が起こるのですか?少なくとも私のクアッドコアラップトップは、装飾がまだ表示されていませんが、装飾されたすべての要素に視覚的なフィードバックを提供するために何百ものテキストブロック、長方形、画像などを作成する必要があるため、長時間フリーズします。画面に表示されるのは100TextBlockだけなので、実際に必要なのは100TextBlockだけです。他の要素が必要な場合は、要素がマウスオーバーイベントまたはフォーカスを受け取った後でのみです。また、一度に編集される要素は1つだけなので、アプリケーション全体で1つの入力要素(この場合はテキストボックス)だけで十分です。
では、ビュー内のすべての要素に対してすべての装飾要素(または実際の入力要素)を作成せずに同じ装飾を実現するための最良の方法は何でしょうか?
ユースケースを明確にするための装飾されたTextBoxの例:
テキストボックスは、フォーカスがない場合、またはマウスカーソルが現在その上にない場合(状態1)、読み取り専用のTextBlockのように見えます。また、要素には現在値がないため、3つのドット( "...")が表示されます。
マウスカーソルを要素の上に移動すると、TextBlockの周囲に緑色の点線の長方形が表示され、要素を変更できることを示します(状態2)。TextBoxがたまたま読み取り専用だった場合、色は赤になります。
フォーカス要素を受け取った後、実際の値を変更するために使用できる実際のTextBoxに変わります(状態3)。
テキストボックスがフォーカスを失った後、値はデータベースに保存され、値が現在保存されていることを示すために、要素の左側にビジーインジケーターが表示されます(状態4)。
最後に、値が保存され、要素は新しい値を示すアイドル状態に戻ります(状態5)。(実際には、要素には検証やその他の特定の要件に関連するさらに多くの状態がありますが、要素が実際に高度に装飾されていることは確かにわかります。)