2008-12-02 6 views
6

Ich habe Probleme, Silverlight 2.0 zu bekommen, um Text genau so auszulegen, wie ich es möchte. Ich möchte Text mit Zeilenumbrüchen und eingebetteten Links, mit Umbruch, wie HTML-Text in einer Webseite.Silverlight 2.0 - Kann das gewünschte Textumbruchverhalten nicht erhalten

Hier ist der nächste, dass ich gekommen bin:

<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> 

Aber das Problem ist, dass, obwohl die Textblöcke TB1 und TB2 auf der gleichen Linie gehen, denn es gibt genug Platz für sie vollständig ist, tb3 wird weiter nicht Beginnen Sie auf der gleichen Linie wie der vorherige Block, obwohl es in den folgenden Zeilen eingewickelt wird.

Ich möchte, dass jeder Textblock beginnt, wo der vorherige endet, in der gleichen Zeile. Ich möchte Click-Event-Handler auf einen Teil des Textes setzen. Ich möchte auch Absatzpausen. Im Wesentlichen versuche ich, das Fehlen von FlowDocument- und Hyperlink-Steuerelementen in Silverlight 2.0-Teilmenge von XAML zu umgehen.

Warum nicht läuft für den Nicht-klickbaren Text:


Um die Fragen in den Antworten gestellt beantworten? Wenn ich einzelne TextBlocks nur für den anklickbaren Text verwende, leiden diese Textabschnitte immer noch unter dem oben dargestellten Wrapping-Problem. Und der TextBlock kurz vor dem Link und der TextBlock kurz danach. Im Wesentlichen alles. Es sieht nicht so aus, als hätte ich viele Möglichkeiten, mehrere Runs im selben TextBlock zu platzieren.

Teilen der Links aus dem anderen Text mit RegExs und Schleifen ist nicht das Problem überhaupt, das Problem ist Display-Layout.

Warum nicht jedes Wort in einen einzelnen TextBlock in einem WrapPanel einfügen Abgesehen davon, dass es sich um einen hässlichen Hack handelt, funktioniert das bei Zeilenumbrüchen nicht gut - das Layout ist falsch.

Es würde auch die Unterstreichung von verknüpften Text in eine gestrichelte Linie machen.

Hier ist ein Beispiel mit jedem Wort in einem eigenen TextBlock. Versuchen Sie es auszuführen, beachten Sie, dass der Zeilenumbruch überhaupt nicht an der richtigen Stelle angezeigt wird.

<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> 

Was ist mit den LinkLabelControl als here und here. Es hat die gleichen Probleme wie der obige Ansatz, da es in etwa gleich ist. Versuchen Sie, das Beispiel auszuführen und den Linktext länger und länger zu machen, bis es umgebrochen wird. Beachten Sie, dass die Verknüpfung in einer neuen Zeile beginnt, was nicht der Fall sein sollte. Machen Sie den Linktext noch länger, so dass der Linktext länger als eine Zeile ist. Beachten Sie, dass es nicht umwickelt, es schneidet ab. Dieses Steuerelement verarbeitet keine Zeilenumbrüche und Absatzunterbrechungen.

Warum in läuft, legen Sie den Text nicht alle Klicks auf die enthaltenden TextBlock- erkennen und herauszufinden, welche Lauf Runs Mausereignisse nicht, wurde angeklickt haben, aber das enthält TextBlock- tut. Ich kann keinen Weg finden zu überprüfen, ob der Lauf unter der Maus ist (IsMouseOver ist in SilverLight nicht vorhanden) oder um die Begrenzungsgeometrie des Laufs zu finden (keine Clip-Eigenschaft).

Es gibt VisualTreeHelper.FindElementsInHostCoordinates()

Der folgende Code verwendet VisualTreeHelper.FindElementsInHostCoordinates, um die Steuerelemente unter dem Klick zu erhalten. Die Ausgabe listet den TextBlock, aber nicht den Run auf, da ein Run kein UIElement ist.

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; 
} 

einen leeren Textblock mit einer Marge auf Platz folgenden Inhalts auf eine folgende Zeile verwenden

ich diese eine noch denken bin. Wie berechnen Sie die richtige Breite für einen Zeilenumbruchblock, um folgenden Inhalt auf die folgende Zeile zu erzwingen? Zu kurz und der folgende Inhalt befindet sich immer noch in derselben Zeile auf der rechten Seite. Zu lang und der "Zeilenumbruch" wird in der folgenden Zeile sein, mit Inhalt danach. Sie müssten die Pausen ändern, wenn die Größe des Steuerelements geändert wird.

Einige der Code hierfür lautet:

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

Können Sie einen Screenshot des Effekts posten, den Sie erhalten möchten? Das Xaml oben hat keine Links, aber Sie verweisen auf Links in Ihrer Frage. – Bryant

+0

Bryant: schau dir irgendeine Webseite an. – Anthony

Antwort

0

Eine sehr interessante Frage. Möglicherweise müssen Sie ein eigenes benutzerdefiniertes Steuerelement erstellen, um mit diesem Layouttyp umgehen zu können. Sie können Runs verwenden, aber eine transparente Leinwand über jedem Lauf überlagern, sodass Sie das Klickereignis behandeln können, das mit diesem Lauf verknüpft ist. Keine einfache Lösung, aber ich denke, es wäre möglich.

Bitte lassen Sie mich wissen, was Sie kommen.

+0

Ich habe ein schlechtes Gefühl über den Ausdruck "interessante Frage". – Anthony

29

Warum können Sie nicht Läufe verwenden?

Verwenden Sie Läufe, um alle Werte zu verknüpfen, die keine Ereignisse haben, dann diejenigen, die Ereignisse in ihren eigenen Textblock ausbrechen, spülen Schaum wiederholen.

Es scheint mir, dass Sie dies mit RegEx und einigen Schleifen tun können. Sieh dir Jesse Libertys Beitrag im Wrap-Panel an und sieh nach, ob das irgendwelche Gedanken fördert. http://silverlight.net/blogs/jesseliberty/archive/2008/12/03/the-wrap-panel.aspx

hth

+0

Ich habe das in der obigen Frage angesprochen. – Anthony

0

Sie versuchen Runs mit konnte nur in Ihrem Textblock, und einen einzigen Klick-Handler für den gesamten Textblock verwenden. Der Handler kann dann die Quelle ausfindig machen, die die Koordinaten des Klickereignisses verwendet, herausfinden, ob es eine Verknüpfung ist (jeder Lauf, bei dem es sich um einen Link handeln kann, kann einen bestimmten x haben: Name, oder Sie könnten sogar Ihren eigenen Lauf ableiten) und die richtige Funktionalität aufrufen dieser Link.

Ich habe es noch nie versucht, aber das ist die Art, wie ich versuchen würde, das Problem zu lösen.

+0

Ich versuche das zu tun, aber wie findest du den Lauf? Sie haben die Koordinaten des Klickereignisses, aber ich sehe nicht, wie die Grenzen des Laufs gefunden werden. – Anthony

0

Ich denke, der beste Weg, dies zu tun wäre, jedes Wort zu einem Textblock zu haben und dann einfach die Wörter an die richtigen Event-Handler für bestimmte Abschnitte anzuhängen. Dadurch erhalten Sie den gewünschten Umbruch und für das Einrücken auf das erste Wort können Sie den linken Rand festlegen.

Siehe diesen Artikel für ein Beispiel, in dem etwas Ähnliches mit Text und dem Wrap-Panel gemacht wird. http://jesseliberty.com/2008/12/03/the-wrap-panel/

+0

Ich habe ein Beispiel für diese Technik falsch geschrieben. – Anthony

+0

Sie können dieses Problem umgehen, indem Sie Ihre Zeilenumbrüche in einen Textblock aufteilen und entweder den linken/rechten Rand oder die Breite der Zeilenumbrüche so einstellen, dass sie der Breite der Seitenfläche entsprechen. zwingt sie, auf ihrer eigenen Linie zu sein. Nicht perfekt, aber es könnte das Beste sein, was Sie tun können. – Tom

0

Zwar gibt es keine IsMouseOver type-Eigenschaft ist, können Sie bei Verwendung VisualTreeHelper.FindElementsInHostCoordinates aussehen könnte()

+0

Schöne Idee, wusste ich nicht über diese Funktion. Ich habe es oben besprochen. – Anthony

0

Ich bin mir nicht sicher, ob Sie die Kommentare auf Ihre Kommentare Kontrolle sind oder nicht, weil Sie nicht ein paar Dinge ansprechen, die ich in meinen Kommentaren zu dir gesagt habe. Der Grund dafür, dass Sie keine Läufe mit VisualTreeHelper.FindElementsInHostCoordinates() finden können, liegt daran, dass UIElements nur zurückgegeben werden und Läufe keine UIElements sind. Wenn Sie diese Methode mit dem Vorschlag kombinieren, keine Runs zu verwenden, dann sollten Sie in Ordnung sein, oder?

Die, jedes Wort als Textblock ist nicht wirklich so schlecht von einem "Hack" und Sie können das Problem von Zeilenumbrüchen umgehen, indem Sie die Zeilenumbrüche in ihren eigenen Textblock aufteilen und diesen Textblöcken eine Breite oder einen Rand zuweisen die Breite der Folie, die sie zwingen würde, auf ihrer eigenen Linie zu sitzen. Definitiv nicht die idealste Lösung, aber ich habe nichts anderes gesehen, was noch etwas verspricht.

+0

Ich hatte keine Zeit, dies zu versuchen - Kommentare oben. – Anthony

0
+0

Nein. Das ist nur ein weiterer Fall, in dem jedes Wort in seinen eigenen Textblock gesetzt wird. Es hat schwerwiegende Probleme mit Zeilen- und Absatzumbrüchen, wie in der Frage erwähnt. – Anthony

+0

Ändern Sie auch den Linktext in diesem Beispiel auf "Links mit Langtext werden von diesem Steuerelement überhaupt nicht umbrochen". Die Verknüpfung beginnt jetzt in einer neuen Zeile, wenn dies nicht der Fall ist. WrapPanel hat keine Möglichkeit, die Verknüpfung in einzelne Wörter zu zerlegen. Was wäre schlecht, wenn der Link unterstrichen wäre. – Anthony

+0

Oder ändern Sie den Link zu "[link =" http: //www.silverlightshow.net "target =" _ blank "] der schnelle braune Fuchs sprang über den laxy Hund der schnelle braune Hund sprang über den faulen Hund [/ link]" - der Linkbutton kann überhaupt nicht wickeln. – Anthony

0

Versuchen Sie folgendes: http://blogs.msdn.com/delay/archive/2007/09/10/bringing-a-bit-of-html-to-silverlight-htmltextblock-makes-rich-text-display-easy.aspx

Die HtmlTextBlock für Silverlight. Es ist nicht wirklich ein abgeschlossenes Konzept, aber es könnte ein guter Ausgangspunkt sein.

+0

es ist eine gute Kontrolle, und wenn die Links klickbar waren, dann wäre es genau das, was ich wollte. Aber es bringt den ganzen Text in Läufe. Und sie sind nicht anklickbar. Siehe Kommentare in der Frage. – Anthony

+0

, um es klar zu machen: das ist, was ich wollte, aber wenn die Links nicht anklickbar sind, ist es nicht so sehr ein "Ausgangspunkt" als eine Sackgasse mit einem Maschendrahtzaun, durch den ich das Ziel sehen kann. – Anthony

2

Ich werde ein paar Antworten auf meine eigene Frage stellen in, auf das, was ich gefunden habe:

1) Sie diese mit einem Strömungs Dokument in der Vollfett Desktop WPF leicht tun können voll von Absatz, Hyperlink, Lauf und verwandten Objekten.

Dies ist, was ich jetzt mache, ich versuche nicht, dieses Problem in Silverlight mehr zu lösen.

2) Verwenden Silverlight 4 Sie können dies nicht tun, in Silverlight 2 oder 3 jedoch Silverlight 4 hat ein Richtextkontrolle, die, wenn nur lesbar, mit Inline-Hyperlinks diese Art der Anzeige von Strömungs- Layout unterstützt, und so wirkt wie eine eingeschränkte Version von FlowDocument und verwandte Klassen von WPF. Silverlight 4 ermöglicht auch eingebetteten Web-Browser-Steuerelement, HTML-Inhalt anzuzeigen, wenn Sie es über Windows-Versionen (IE-Versionen) und auf Mac und möglicherweise anderen Plattformen dasselbe aussehen lassen können.

3) Sie können sich wahrscheinlich durch den Aufbau eine Reihe von HTML so etwas wie dies in Silverlight (alle Versionen) tun und in den DOM Injizieren es in dem Teil der Seite zu zeigen, die außerhalb des Silverlight-Steuerelement ist . Es klingt durchaus machbar, aber meiner Meinung nach zu schlau um die Hälfte.

Verwandte Themen