2008-12-02 8 views
6

Mam problem z ustawieniem Silverlight 2.0 w celu ułożenia tekstu dokładnie tak, jak chcę. Chcę tekstu z podziałami linii i osadzonymi linkami, z zawijaniem, jak tekst HTML na stronie internetowej.Silverlight 2.0 - Nie można uzyskać zachowania zawijania tekstu, które chcę.

Oto najbliżej że przyszedłem:

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

Ale problemem jest to, że chociaż TB1 bloki tekstowe i TB2 pójdzie na tej samej linii, ponieważ nie ma dość miejsca dla nich całkowicie, TB3 roku nie będzie zacznij od tej samej linii co poprzedni, nawet jeśli zostanie zawinięty do następnych linii.

Chcę, aby każdy blok tekstu zaczął się tam, gdzie kończy się poprzedni, w tym samym wierszu. Chcę dodać obsługę zdarzeń kliknięcia do niektórych tekstów. Też chcę przerwy na akapity. Zasadniczo staram się obejść brak kontroli FlowDocument i Hiperłącze w podzestawie XAML w Silverlight 2.0.


Aby odpowiedzieć na pytania stawiane w odpowiedziach:

Dlaczego nie korzystać z tras dla tekstu nieklikalna? Jeśli po prostu użyję pojedynczych bloków tekstowych tylko w klikalnym tekście, to te bity tekstu będą nadal cierpieć z powodu opisanego powyżej problemu z zawijaniem. I TextBlock tuż przed linkiem, a TextBlock zaraz po. Zasadniczo to wszystko. Nie wygląda na to, że mam wiele okazji do umieszczenia wielu przebiegów w tym samym TextBlock.

Dzielenie linków z innego tekstu za pomocą RegEx i pętli nie jest w ogóle problemem, problemem jest układ ekranu.

Dlaczego nie umieścić każde słowo w indywidualnej TextBlock w WrapPanel Oprócz bycia brzydki hack, to nie grać w ogóle dobrze z wierszami - układ jest nieprawidłowy.

Utworzy również styl podkreślenia połączonego tekstu w przerywaną linię.

Oto przykład każdego słowa w jego własnej blokadzie tekstowej. Spróbuj uruchomić, pamiętaj, że linia podziału nie jest wyświetlana we właściwym miejscu.

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

co z LinkLabelControl jako here i here. Ma takie same problemy jak powyższe podejście, ponieważ jest prawie taki sam. Spróbuj uruchomić próbkę i spraw, aby tekst linku był dłuższy i dłuższy, dopóki się nie opakuje. Zwróć uwagę, że link zaczyna się od nowej linii, której nie powinien. Zwiększ tekst linku, aby tekst linku był dłuższy niż linia. Zwróć uwagę, że w ogóle się nie zawija, odcina. Ta kontrolka również nie obsługuje podziałów linii i akapitów.

Dlaczego nie umieścić tekst wszystkim w seriach, wykryć kliknięć na zawierającego TextBlock i wypracować który prowadzony był kliknięciu Działa nie mają zdarzenia myszy, ale zawierający TextBlock robi. Nie mogę znaleźć sposobu sprawdzenia, czy przebieg jest pod myszą (IsMouseOver nie jest obecny w SilverLight) ani w celu znalezienia geometrii granicznej przebiegu (bez właściwości clip).

nie

jest VisualTreeHelper.FindElementsInHostCoordinates()

poniżej kodu wykorzystuje VisualTreeHelper.FindElementsInHostCoordinates, aby uzyskać kontrolę pod kliknięciem. Dane wyjściowe zawierają TextBlock, ale nie Run, ponieważ Run nie jest UIElement.

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

Użyj pusty blok tekstu z marginesem do przestrzeni następujące treści na o następującej linii

ja wciąż myśli o tym. Jak obliczyć właściwą szerokość bloku łamania linii, aby wymusić następującą zawartość na następujący wiersz? Zbyt krótki, a następująca treść nadal będzie znajdować się w tym samym wierszu po prawej stronie. Zbyt długi i "linebreak" będzie w następującym wierszu, z treścią po nim. Będziesz musiał zmienić rozmiar przerw po zmianie rozmiaru kontrolki.

Niektóre kodzie to:

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

Czy możesz opublikować zrzut ekranu przedstawiający efekt, który chcesz uzyskać? Xaml na górze nie ma jeszcze żadnych linków, ale wciąż odnosisz się do linków w twoim pytaniu. – Bryant

+0

Bryant: spójrz na dowolną stronę internetową. – Anthony

Odpowiedz

0

bardzo ciekawe pytanie. Być może trzeba będzie utworzyć własny niestandardowy formant, aby obsłużyć ten typ układu. Możesz użyć Runów, ale nakładać przezroczyste płótno na każdym z nich, aby móc obsłużyć zdarzenie kliknięcia powiązane z tym uruchomieniem. Wcale nie jest to łatwe rozwiązanie, ale myślę, że byłoby to możliwe.

Proszę dać mi znać, z czym przyszedłeś.

+0

Mam złe przeczucie co do frazy "interesujące pytanie". – Anthony

29

Dlaczego nie możesz używać biegania?

Stosuj przebiegi do połączenia wszystkich wartości, które nie będą miały zdarzeń, a następnie te, które mają zdarzenia, dzielą się na swój własny blok tekstowy, a następnie powtarzaj powtarzanie.

Wydaje mi się, że powinieneś być w stanie to zrobić z RegEx i trochę pętli. Sprawdź posta Jesse Liberty na panelu zawijania i zobacz, czy to sprzyja jakiejkolwiek myśli. http://silverlight.net/blogs/jesseliberty/archive/2008/12/03/the-wrap-panel.aspx

HTH

+0

Odniosłem się do tego w powyższym pytaniu. – Anthony

0

Można spróbować użyć działa tylko wewnątrz TextBlock i używać jednego kliknięcia obsługi dla całej TextBlock. Handler może następnie zlokalizować Run źródła za pomocą współrzędnych zdarzenia kliknięcia, dowiedzieć się, czy jest to łącze (każdy Run, który jest linkiem może mieć konkretną nazwę x: lub możesz nawet wywodzić swój własny Run) i wywołać odpowiednią funkcjonalność dla ten link.

Nigdy tego nie próbowałem, ale w ten sposób spróbuję rozwiązać problem.

+0

Próbuję to zrobić, ale jak zlokalizować przebieg? Masz współrzędne kliknięcia, ale nie rozumiem, jak znaleźć granice przebiegu. – Anthony

0

Myślę, że najlepszym sposobem, aby to zrobić, byłoby, aby każde słowo było blokiem tekstowym, a następnie wystarczy dołączyć słowa do odpowiednich programów obsługi zdarzeń, które chcesz dla poszczególnych sekcji. To da ci zawijanie, które chcesz i wcięcie na pierwszym słowie, możesz ustawić jego lewy margines.

Zobacz ten artykuł, aby zobaczyć przykład, w którym coś podobnego robi się z tekstem i panelem zawijania. http://jesseliberty.com/2008/12/03/the-wrap-panel/

+0

Podaję przykład tej techniki, która idzie źle. – Anthony

+0

Możesz obejść ten problem, rozdzielając linie łamów w blok tekstu i ustawiając lewy/prawy margines lub szerokość bloków tekstowych na linii jako szerokość wrappanelu. zmuszając ich do wejścia na własną linię. Nie idealne, ale może to być najlepsze, co możesz zrobić. – Tom

0

Choć nie ma właściwość typu IsMouseOver, można spojrzeć na użyciu VisualTreeHelper.FindElementsInHostCoordinates()

+0

Niezły pomysł, nie wiedziałem o tej funkcji. Omówiłem to powyżej. – Anthony

0

Nie jestem pewien, czy jesteś sprawdzanie komentarze na komentarze, czy też nie, ponieważ nie adres kilka rzeczy, które powiedziałem w moich komentarzach z powrotem na twoje. Powodem, dla którego nie można znaleźć uruchomień przy użyciu VisualTreeHelper.FindElementsInHostCoordinates(), jest to, że zwraca tylko UIElements, a Runs nie są UIlements. Jeśli połączysz tę metodę z sugestią, aby nie używać żadnych przebiegów, powinieneś być w porządku, prawda?

Każde słowo jako blok tekstu nie jest tak naprawdę "hackowe" i można obejść problem z liniami podziału, oddzielając linie podziału na własny blok tekstu i przypisując blokom tekstowym szerokość lub margines równy szerokość panelu, który zmusiłby ich do usadowienia się na własnej linii. Zdecydowanie nie jest to najbardziej idealne rozwiązanie, ale nie widzę jeszcze niczego, co by wskazywało na jakąkolwiek obietnicę.

+0

Nie miałem czasu, aby to wypróbować - komentarze powyżej. – Anthony

0
+0

Nie. To tylko kolejny przypadek umieszczenia każdego słowa w jego własnym bloku tekstowym. Ma poważne problemy z łamaniem wierszy i akapitów, jak zaznaczono w pytaniu. – Anthony

+0

Również, chnge tekst łącza w tym przykładzie, aby "linki z długim tekstem nie były w ogóle zawijane przez tę kontrolę". Link zaczyna się teraz w nowej linii, gdy nie powinien. WrapPanel nie ma sposobu na obejście tego linka w oddzielne słowa. Co byłoby złe, gdyby link był podkreślony. – Anthony

+0

Lub zmień link na "[link =" http: //www.silverlightshow.net "target =" _ blank "] szybki brązowy lis przeskoczył nad zwinnym psem, którego szybki brązowy pies przeskoczył nad leniwym psem [/ link]" - link nie może w ogóle zawijać. – Anthony

0

Spróbuj tego: http://blogs.msdn.com/delay/archive/2007/09/10/bringing-a-bit-of-html-to-silverlight-htmltextblock-makes-rich-text-display-easy.aspx

HtmlTextBlock dla Silverlight. To naprawdę nie jest koncepcja, ale może to być dobry punkt wyjścia.

+0

to dobra kontrola, a jeśli linki były klikalne, byłby to po prostu to, co chciałem. Ale nakłada cały tekst na biegi. I nie są klikalne. Zobacz komentarze w pytaniu. – Anthony

+0

, aby było jasne: tego właśnie chciałem, ale chyba że linki są klikalne, to nie tyle "punkt wyjścia", co ślepy zaułek z ogrodzeniem z siatki, przez które widzę cel. – Anthony

2

mam zamiar wprowadzić kilka odpowiedzi na moje pytanie, w oparciu o to, co znalazłem:

1) można to zrobić łatwo w pełnotłusty pulpitu WPF z dokumentem przepływu pełen akapit, hiperłącze, uruchom i powiązane obiekty.

To właśnie teraz robię, nie próbuję już więcej rozwiązywać tego problemu w Silverlight.

2) Wykorzystanie Silverlight 4 Nie można tego zrobić w Silverlight 2 lub 3. Jednakże Silverlight 4 posiada regulację RichTextArea które gdy tylko do odczytu, wspiera tego rodzaju wyświetlacza układ przepływu z inline hiperłączy, a więc aktów jak uproszczona wersja FlowDocument i powiązanych klas z WPF. Silverlight 4 pozwala również na sterowanie przeglądarką internetową w celu wyświetlania treści HTML, jeśli możesz sprawić, że będzie wyglądała tak samo w różnych wersjach systemu Windows (to znaczy wersjach IE) oraz na Macu i potencjalnie na innych platformach.

3) Prawdopodobnie można zrobić coś takiego w Silverlight (dowolna wersja) poprzez budowanie ciąg HTML i wstrzykiwanie go do DOM aby pokazać go w części strony, która znajduje się poza kontrolą Silverlight . Brzmi to w pełni sprawnie, ale moim zdaniem zbyt sprytne o połowę.