キャンバスとその中の要素をクライアント領域全体に引き伸ばします

デスクトップアプリケーションでの作業中に、次の問題に遭遇しました:表示の設定(ContentControlのバインディングを介して接続されたControlTemplateとして実装)を備えたグラフィック要素があり、追加のグループを既存の設定に追加する必要がありました。 既存のインターフェイスを詰まらせないために、これらの設定のリストをExpander要素に配置することを決定しました。必要に応じて展開でき、残りの時間はチャートが最大使用可能スペースを占有します。



要素を配置する1つの方法は、カットの下です。



その結果、次の要素の階層が得られました。



<TabItem> <Grid> <Grid.RowDefenitions> <RowDefenition Height="Auto" /> <RowDefenition /> </Grid.RowDefenitions> <Expander Header=" " Grid.Row="0" IsExpanded="False" MinWidth="270"> <   1 /> <   2 /> <   n /> </Expander> <ContentControl <!--   --> Grid.Row="1" /> </Grid> </TabItem>
      
      







このコンテナはタブ内のスペースを完全に占有し、幅自体に要素を行ごとに引き伸ばすことができるため、グリッドを使用します。



タブの上部に配置されたエキスパンダー、スペクトルを操作するためのコントロール-そのすぐ下。 ただし、結果は期待通りではありませんでした。Expanderを展開すると、チャートコントロールが下に移動するため、Expanderを閉じて結果を確認するか、チャートに残っている画面の半分をスクロールする必要があります。



同じエキスパンダーを使用して、カスタムコントロールを介して開くように開くというアイデアがありました。 これには、Canvasコンテナが理想的です。それに含まれる各要素にZIndex(レイヤー深度)を指定できるのはそのためです。 いくつかのレイアウトオプションを試しましたが、その1つを以下に示します。



 <TabItem> <Grid> <Canvas> <Expander Header=" " IsExpanded="False" Panel.ZIndex="1" MinWidth="270" Canvas.Right="10" > <   1 /> <   2 /> <   n /> </Expander> <ContentControl <!--   --> Canvas.Top="25" /> </Canvas> </Grid> </TabItem>
      
      







しかし、ここでも失望が待っていました.Canvasはまったく表示されませんでした(デフォルトでは幅と高さ= 0であるため)、またはその中の要素はサイズが小さすぎる、またはその逆でした-それらは画面の可視性の制限を超えました。



以下を達成する必要がありました。タブのクライアント領域全体にCanvasを引き伸ばすこと。 Canvas Expanderの右上部分に固定幅を配置し、その下に残りの領域全体のContentControlを引き伸ばします。



情報の検索、フィルター処理、および要約に時間を費やした後、次の解決策を見つけました。タブ内にDockPanelを配置しました。 このコンテナは、内部の要素の寸法を自動的に設定することもできます。 DockPanelのLastChildFill =“ True”プロパティを設定して、残りの領域全体に最後の要素を引き伸ばします。 DockPanelに名前を付けます。たとえば、x:Name =“ spectrumDock”とし、その中にCanvasを配置します。これをパネルの上部に「アタッチ」します(ただし、配置には特別な意味があります)。 Canvas内に、次のようにExpanderとContentControlを配置します。



  <DockPanel x:Name="spectrumDock" LastChildFill="True"> <Canvas> <Expander Header=" " IsExpanded="False" Panel.ZIndex="1" MinWidth="270" Canvas.Right="10" > <   1 /> <   2 /> <   n /> <Expander.Effect> <DropShadowEffect BlurRadius="6" Direction="270" ShadowDepth="1" Opacity="0.5"/> </Expander.Effect> </Expander> <ContentControl Content="{Binding Path=ControlTemplateName}" Canvas.Top="25" Height="{Binding ElementName=spectrumDock, Path=ActualHeight, Converter={StaticResource SizeTrimmerConverter}, ConverterParameter='25'}" Width="{Binding ElementName=spectrumDock, Path=ActualWidth}" /> </Canvas> </DockPanel>
      
      





... Expanderの影は、この要素が他の要素の上にあるという感覚を作り出します。 寸法を設定するために、ContentControlは単にDockPanelのwidthプロパティとheightプロパティ(つまりActual)のバインディングを使用します。 ただし、「BUT」が1つありました。ContentControlは、25ピクセル下にシフトされ、DockPanelの高さと等しい高さを持っているため、これらの同じ25ピクセルだけ表示境界を超えて移動します。 DockPanelの高さから25ピクセルを引いた値をContentControlにバインドする必要があります。 この問題は非常に簡単に解決できます-インデントに必要なピクセル数をパラメーターとして受け取るコンバーターを使用して:



 namespace _ { [ValueConversion(typeof(double), typeof(double))] public class SizeTrimmerConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (double)value - ConvertParameter(parameter); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return (double)value + ConvertParameter(parameter); } private double ConvertParameter(object parameter) { string _stringValue = parameter.ToString(); double _result = 0; double.TryParse(_stringValue, out _result); return _result; } } }
      
      





メインコントロール(UserControlまたはフォーム)の説明で、名前空間へのリンクを指定します。



 xmlns:Converters="clr-namespace:_;assembly=_"
      
      







...およびリソースでコンバータを説明します。



 < .Resources> <Converters:SizeTrimmerConverter x:Key="SizeTrimmerConverter" /> </ .Resources>
      
      





...コンバーターは別のライブラリーにあるため、assembly_nameが示されます。



その結果、すべてが期待どおりになりました。 厳密に判断しないようお願いします。この方法は「松葉杖」かもしれませんが、WPF + XAMLテクノロジーの使用経験はまだ十分ではありません。 私の経験が誰かに役立つことを願っています。



All Articles