WPFドキュメント内の相対的に配置された要素

数か月前、WPFを使用してインターフェイスを実装する必要がありました。 主に使用されるFlowDocument WebページのスタイルでUIをできる限り厳密に整理する必要がありました。

CSSを使用してHTML要素を配置する自由に慣れているため、ネストされた要素の相対的な配置の解決策を見つけることができませんでした。 フローティングWPFドキュメントでは、Top、Left、Right、Bottomの各プロパティは完全に存在しません。 MSDNはFigureクラスのみを発行しました。 ただし、FlowDocumentScrollViewerを使用する場合、Horizo​​ntalOffsetおよびVerticalOffsetは機能しません。 Google検索も役に立たなかった。

ただし、ソリューションは単純ではありませんでした。



ブラウザエンジンの仕組み


内部実装に関する最も興味深い情報は、WebKitによって提供されます。 ブログは、プロジェクトのソースコードを勉強したくないが、そのアーキテクチャについて知りたい人にとって貴重な情報源です。



特に興味深いのは、WebCore Renderingシリーズの投稿です。 このページには、「相対位置付けは文字通りペイント時の翻訳にすぎない」という問題の解決を促した主なフレーズも含まれていました。



この「仮定」で武装して、WPFの腸で似たようなものを見つけることにしました。



テキスト効果


UIElementの場合、通常、RenderTrasformと、Translate、Rotate、Scaleの形式の2D変換を使用する場合、テキストを含むオブジェクトに対して同じメカニズムが提供されます。 すべての変換のコンテナはTextEffectクラスです。



それでは、実装に取り​​かかりましょう。 ブログページの例を例として使用します。





<div style="border:5px solid black; padding:20px; width:300px; margin-left:auto; margin-right:auto"> Here is a line of text. <span style="position:relative;top:-10px; background-color:#eeeeee">This part is shifted<br> up a bit</span>, but the rest of the line is in its original position. </div>
      
      





同じ例ですが、WPFのみで、位置付けはありません:





 <FlowDocumentScrollViewer> <FlowDocumentScrollViewer.Document> <FlowDocument Name="doc" FontFamily="Verdana" FontSize="12px" LineHeight="18px"> <Paragraph Padding="20px" BorderThickness="5px" BorderBrush="Black"> Here is a line of text. <Span Name="shiftedText" Background="#EEE">This part is shifted<LineBreak/> up a bit </Span>, but the rest of the line is in its original position. </Paragraph> </FlowDocument> </FlowDocumentScrollViewer.Document> </FlowDocumentScrollViewer>
      
      





TextEffectを適用する前に、 Runタイプでのみ機能することを知っておく必要があります スパンまたはドキュメント内の別の要素に適用した場合、効果は観察されません。



効果を適用します。



 void DoEffect() { foreach (var run in shiftedText.Inlines.OfType<Run>()) { TextEffect f = new TextEffect(); TranslateTransform t = new TranslateTransform(0, -10d); f.Transform = t; int selectionStart = doc.ContentStart.GetOffsetToPosition(run.ElementStart); int selectionLength = run.ElementStart.GetOffsetToPosition(run.ElementEnd); f.PositionStart = selectionStart; f.PositionCount = selectionLength; run.TextEffects.Add(f); } }
      
      





キャンセルするコード:



 void UndoEffect() { foreach (var run in shiftedText.Inlines.OfType<Run>()) { run.TextEffects.Clear(); } }
      
      





したがって、望ましい効果を得ることができました。 コードが他の人にも役立つことを願っています。

サンプルを使用してプロジェクトにリンクます。




All Articles