6

Silverlight 2.0 でテキストを思い通りにレイアウトするのに苦労しています。Web ページの HTML テキストのように、改行と埋め込みリンクを含むテキストが必要です。

ここに私が来た最も近いものがあります:

<UserControl x:Class="FlowPanelTest.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls" 
    Width="250" Height="300">
    <Border BorderBrush="Black" BorderThickness="2" >
      <Controls:WrapPanel> 
      <TextBlock x:Name="tb1" TextWrapping="Wrap">Short text. </TextBlock>
      <TextBlock x:Name="tb2" TextWrapping="Wrap">A bit of text. </TextBlock>
      <TextBlock x:Name="tb3" TextWrapping="Wrap">About half of a line of text.</TextBlock>
      <TextBlock x:Name="tb4" TextWrapping="Wrap">More than half a line of longer text.</TextBlock>
      <TextBlock x:Name="tb5" TextWrapping="Wrap">More than one line of text, so it will wrap onto the  following line.</TextBlock>
      </Controls:WrapPanel>
      </Border>
</UserControl>

しかし問題は、テキスト ブロック tb1 と tb2 は完全に十分なスペースがあるため同じ行に移動しますが、tb3 以降は、次の行に折り返されても、前のブロックと同じ行で開始されないことです。

各テキスト ブロックを、同じ行で前のテキスト ブロックが終了する場所から開始したい。一部のテキストにクリック イベント ハンドラを配置したいと考えています。段落区切りも欲しい。基本的に、Silverlight 2.0 の XAML サブセットに含まれる FlowDocument コントロールと Hyperlink コントロールの欠如を回避しようとしています。


回答で提示された質問に回答するには:

クリックできないテキストにランを使用しないのはなぜですか? クリック可能なテキストに対してのみ個々の TextBlocks を使用すると、それらのテキストの一部が上記の折り返しの問題に悩まされます。そして、リンクの直前の TextBlock と直後の TextBlock です。本質的にそれのすべて。同じ TextBlock に複数のランを配置する機会があまりないようです。

正規表現とループを使用して他のテキストからリンクを分割することはまったく問題ではありません。問題は表示レイアウトです。

WrapPanel 内の個々の TextBlock に各単語を配置しない理由はありません。見苦しいハックであることは別として、これは改行ではまったくうまく機能しません。レイアウトが正しくありません。

また、リンクされたテキストの下線スタイルを破線にします。

それぞれの単語が独自の TextBlock にある例を次に示します。実行してみてください。改行が正しい場所にまったく表示されないことに注意してください。

<UserControl x:Class="SilverlightApplication2.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls" 
    Width="300" Height="300">
    <Controls:WrapPanel>
        <TextBlock  TextWrapping="Wrap">Short1 </TextBlock>
        <TextBlock  TextWrapping="Wrap">Longer1 </TextBlock>
        <TextBlock  TextWrapping="Wrap">Longerest1 </TextBlock>
        <TextBlock  TextWrapping="Wrap">
                <Run>Break</Run>
                <LineBreak></LineBreak>
        </TextBlock>
        <TextBlock  TextWrapping="Wrap">Short2</TextBlock>
        <TextBlock  TextWrapping="Wrap">Longer2</TextBlock>
        <TextBlock  TextWrapping="Wrap">Longerest2</TextBlock>
        <TextBlock  TextWrapping="Wrap">Short3</TextBlock>
        <TextBlock  TextWrapping="Wrap">Longer3</TextBlock>
        <TextBlock  TextWrapping="Wrap">Longerest3</TextBlock>
    </Controls:WrapPanel>
</UserControl>

herehereのような LinkLabelControl はどうですか。上記のアプローチとほとんど同じであるため、同じ問題があります。サンプルを実行してみて、リンク テキストが折り返されるまでどんどん長くしてください。リンクは新しい行で始まることに注意してください。リンク テキストをさらに長くして、リンク テキストが 1 行よりも長くなるようにします。まったくラップしないことに注意してください。このコントロールは、改行や段落の区切りも処理しません。

テキストをすべてランに入れて、含まれている TextBlock のクリックを検出し、どのランがクリックされたかを調べて みませんか? ランにはマウス イベントがありませんが、含まれている TextBlock にはあります。ランがマウスの下にあるかどうかを確認する方法 (Silverlight には IsMouseOver が存在しない) や、ランの境界ジオメトリを見つける方法 (クリップ プロパティがない) を見つける方法が見つかりません。

VisualTreeHelper.FindElementsInHostCoordinates()があります

以下のコードは、VisualTreeHelper.FindElementsInHostCoordinates を使用して、クリックでコントロールを取得します。Run は UiElement ではないため、出力には TextBlock がリストされますが、Run はリストされません。

private void theText_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    // get the elements under the click
    UIElement uiElementSender = sender as UIElement;
    Point clickPos = e.GetPosition(uiElementSender);
    var UiElementsUnderClick = VisualTreeHelper.FindElementsInHostCoordinates(clickPos, uiElementSender);

    // show the controls
    string outputText = "";
    foreach (var uiElement in UiElementsUnderClick)
    {
        outputText += uiElement.GetType().ToString() + "\n";
    }
    this.outText.Text = outputText;
}

余白のある空のテキスト ブロックを使用して、次のコンテンツを次の行に配置します

私はまだこれについて考えています。次のコンテンツを次の行に強制するために、改行ブロックの適切な幅をどのように計算しますか? 短すぎると、次のコンテンツが同じ行の右側に残ります。長すぎると、「改行」が次の行になり、その後にコンテンツが続きます。コントロールのサイズが変更されたときに、ブレークのサイズを変更する必要があります。

このためのコードの一部は次のとおりです。

    TextBlock lineBreak = new TextBlock();
    lineBreak.TextWrapping = TextWrapping.Wrap;
    lineBreak.Text = " ";
    // need adaptive width 
    lineBreak.Margin = new Thickness(0, 0, 200, 0);
4

9 に答える 9

29

なぜランを使用できないのですか?

実行を使用して、イベントが発生するすべての値を連結します。次に、イベントが発生する値は、独自のテキストブロックに分割され、泡を繰り返し洗い流します。

RegExといくつかのループを使用してこれを実行できるはずです。ラップパネルに関するJesseLibertyの投稿をチェックして、それが何か考えを助長するかどうかを確認してください。 http://silverlight.net/blogs/jesseliberty/archive/2008/12/03/the-wrap-panel.aspx

hth

于 2008-12-04T23:28:54.200 に答える
2

私が見つけたものに基づいて、私自身の質問にいくつかの答えを入れます。

1)これは、段落、ハイパーリンク、実行、および関連オブジェクトでいっぱいのフロー ドキュメントを使用して、完全なデスクトップ WPF で簡単に実行できます。

これは私が現在行っていることであり、Silverlight でこの問題を解決しようとはしていません。

2) Silverlight 4 を使用するSilverlight 2 または 3 ではこれを行うことはできません。ただし、Silverlight 4 には RichTextArea コントロールがあり、読み取り専用の場合、インライン ハイパーリンクを使用したフロー レイアウトのこの種の表示をサポートするため、カットダウン バージョンのように機能します。 FlowDocument および WPF からの関連クラスの。Silverlight 4 では、埋め込み Web ブラウザー コントロールで HTML コンテンツを表示することもできます。これは、Windows バージョン (つまり IE バージョン) と Mac およびその他のプラットフォームで同じように表示できる場合です。

3)おそらく、Silverlight (任意のバージョン) で、HTML の文字列を作成し、それを DOM に挿入して、Silverlight コントロールの外側にあるページの部分に表示することで、このようなことを行うことができます。それは完全に機能するように思えますが、私の意見では、半分賢すぎます。

于 2009-02-02T12:27:54.347 に答える
0

TextBlock内でONLYRunsを使用してみて、TextBlock全体にシングルクリックハンドラーを使用することができます。ハンドラーは、クリックイベントの座標を使用してソースの実行を見つけ、それがリンクであるかどうかを確認し(リンクである各実行は、特定のx:Nameを持つことができます。または、独自の実行を派生させることもできます)、次の適切な機能を呼び出すことができます。そのリンク。

私はそれを試したことがありませんが、これは私が問題を解決しようとする方法です。

于 2008-12-05T13:50:36.393 に答える
0

IsMouseOverタイプのプロパティはありませんが、VisualTreeHelper.FindElementsInHostCoordinates()を使用して確認できます。

于 2008-12-06T18:00:56.670 に答える
0

コメントのコメントで私が言ったことのいくつかに対処しなかったので、コメントのコメントをチェックしているかどうかはわかりません。VisualTreeHelper.FindElementsInHostCoordinates()を使用してランを見つけることができない理由は、UIElementsのみを返し、ランはUIElementsではないためです。ただし、この方法を実行を使用しないという提案と組み合わせると、問題ないはずです。

テキストブロックとしてのすべての単語は、実際には「ハック」としてはそれほど悪くはありません。改行を独自のテキストブロックに分割し、それらのテキストブロックに幅またはマージンを割り当てることで、改行の問題を回避できます。彼らが彼ら自身のラインに座ることを強制するであろうラップパネル。間違いなく最も理想的な解決策ではありませんが、私はまだ約束を示すものを他に見ていません。

于 2008-12-08T14:32:36.840 に答える
0

これを行うための最良の方法は、各単語をテキストブロックにしてから、特定のセクションに必要な正しいイベントハンドラーに単語を添付することだと思います。これにより、必要なラッピングが可能になり、最初の単語のインデントについては、左マージンを設定できます。

同様のことがテキストと折り返しパネルで行われる例については、この記事を参照してください。 http://jesseliberty.com/2008/12/03/the-wrap-panel/

于 2008-12-05T18:12:49.173 に答える
0

これは機能しますか? http://www.silverlightshow.net/items/Silverlight-LinkLabel-control.aspx

于 2008-12-10T16:49:12.740 に答える
0

非常に興味深い質問です。このタイプのレイアウトを処理するには、独自のカスタム コントロールを作成する必要がある場合があります。Runs を使用できますが、各 run の上に透明なキャンバスをオーバーレイして、その run に関連付けられたクリック イベントを処理できるようにします。簡単な解決策ではありませんが、可能だと思います。

何を持ってきたか教えてください。

于 2008-12-03T18:32:58.183 に答える
0

これを試してください: http://blogs.msdn.com/delay/archive/2007/09/10/bringing-a-bit-of-html-to-silverlight-htmltextblock-makes-rich-text-display-easy.aspx

Silverlight の HtmlTextBlock。完成したコンセプトではありませんが、良い出発点になるかもしれません。

于 2008-12-11T00:02:24.690 に答える