23 votos

Ajuste de una cadena en varias líneas

Estoy tratando de ajuste de palabra de una cadena en varias líneas. Cada línea tendrá ancho definido.

Por ejemplo me gustaría conseguir este resultado, si me ajuste a un área de 120 pixeles de ancho.

Lorem ipsum dolor sit amet,
consectetur adipiscing elit. Sed augue
velit, tempor no vulputate sit amet,
dictamen vitae lacus. En vitae ante
justo, ut accumsan sem. Donec
pulvinar, nisi nec sagittis consequat,
sem orci luctus velit, sed elementum
ligula ante nec neque. Pellentesque
habitante morbi tristique senectus et
netus et y más fames ac turpis
egestas. Etiam brindamos est, pellentesque
eget tincidunt ut, egestas en ante.
Nulla vitae vulputate velit. Proin en
congue neque. Cras rutrum sodales
sapien, ut convallis brindamos auctor vel.
Duis, no había nada más pharetra dui, sagittis
varius mauris tristique una. Nam ut
neque id risus tempor hendrerit.
Mecenas ut lacus nunc. Nulla
fermentum ornare rhoncus. Nulla
gravida vestíbulo odio, vel commodo
magna condimentum quis. Quisque
sollicitudin blandit mi, no varius
libero lobortis de la ue. Vestíbulo de la ue
turpis massa, id tincidunt orci.
Curabitur pellentesque urna no risus
adipiscing facilisis. Mauris vel
accumsan purus. Proin quis enim nec
sem tempor vestíbulo de ca vitae augue.

27voto

as-cii Puntos 7028
static void Main(string[] args)
{
    List<string> lines = WrapText("Add some text", 300, "Calibri", 11);

    foreach (var item in lines)
    {
        Console.WriteLine(item);
    }

    Console.ReadLine();
}

static List<string> WrapText(string text, double pixels, string fontFamily, 
    float emSize)
{
    string[] originalLines = text.Split(new string[] { " " }, 
        StringSplitOptions.None);

    List<string> wrappedLines = new List<string>();

    StringBuilder actualLine = new StringBuilder();
    double actualWidth = 0;

    foreach (var item in originalLines)
    {
        FormattedText formatted = new FormattedText(item, 
            CultureInfo.CurrentCulture, 
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(fontFamily), emSize, Brushes.Black);

        actualLine.Append(item + " ");
        actualWidth += formatted.Width;

        if (actualWidth > pixels)
        {
            wrappedLines.Add(actualLine.ToString());
            actualLine.Clear();
            actualWidth = 0;
        }
    }

    if(actualLine.Length > 0)
        wrappedLines.Add(actualLine.ToString());

    return wrappedLines;
}

Agregar WindowsBase y PresentationCore bibliotecas.

12voto

Lorenzo Puntos 12167

El código siguiente, tomado de este blogpost, le ayudará a conseguir su trabajo hecho.

Usted puede usarlo de esta manera:

string wordWrappedText = WordWrap( <yourtext>, 120 );

Por favor, tenga en cuenta que el código no es mío, yo soy sólo un informe de aquí la función principal de su mercancía.

protected const string _newline = "\r\n";

public static string WordWrap( string the_string, int width ) {
    int pos, next;
    StringBuilder sb = new StringBuilder();

    // Lucidity check
    if ( width < 1 )
        return the_string;

    // Parse each line of text
    for ( pos = 0; pos < the_string.Length; pos = next ) {
        // Find end of line
        int eol = the_string.IndexOf( _newline, pos );

        if ( eol == -1 )
            next = eol = the_string.Length;
        else
            next = eol + _newline.Length;

        // Copy this line of text, breaking into smaller lines as needed
        if ( eol > pos ) {
            do {
                int len = eol - pos;

                if ( len > width )
                    len = BreakLine( the_string, pos, width );

                sb.Append( the_string, pos, len );
                sb.Append( _newline );

                // Trim whitespace following break
                pos += len;

                while ( pos < eol && Char.IsWhiteSpace( the_string[pos] ) )
                    pos++;

            } while ( eol > pos );
        } else sb.Append( _newline ); // Empty line
    }

    return sb.ToString();
}

/// <summary>
/// Locates position to break the given line so as to avoid
/// breaking words.
/// </summary>
/// <param name="text">String that contains line of text</param>
/// <param name="pos">Index where line of text starts</param>
/// <param name="max">Maximum line length</param>
/// <returns>The modified line length</returns>
public static int BreakLine(string text, int pos, int max)
{
  // Find last whitespace in line
  int i = max - 1;
  while (i >= 0 && !Char.IsWhiteSpace(text[pos + i]))
    i--;
  if (i < 0)
    return max; // No whitespace found; break at maximum length
  // Find start of whitespace
  while (i >= 0 && Char.IsWhiteSpace(text[pos + i]))
    i--;
  // Return length of text before whitespace
  return i + 1;
}

3voto

tvwxyz Puntos 28

He aquí una versión que se me ocurrió para mi XNA game...

(Tenga en cuenta que se trata de un fragmento, no una correcta definición de la clase. ¡A disfrutar!)

using System;
using System.Text;
using Microsoft.Xna.Framework.Graphics;

public static float StringWidth(SpriteFont font, string text)
{
    return font.MeasureString(text).X;
}

public static string WrapText(SpriteFont font, string text, float lineWidth)
{
    const string space = " ";
    string[] words = text.Split(new string[] { space }, StringSplitOptions.None);
    float spaceWidth = StringWidth(font, space),
        spaceLeft = lineWidth,
        wordWidth;
    StringBuilder result = new StringBuilder();

    foreach (string word in words)
    {
        wordWidth = StringWidth(font, word);
        if (wordWidth + spaceWidth > spaceLeft)
        {
            result.AppendLine();
            spaceLeft = lineWidth - wordWidth;
        }
        else
        {
            spaceLeft -= (wordWidth + spaceWidth);
        }
        result.Append(word + space);
    }

    return result.ToString();
}

0voto

Thorin Puntos 506

Usted puede obtener (aproximado) la anchura de la cadena del Sistema.De dibujo.Gráficos de clase utilizando el MeasureString() método. Si usted necesita un muy preciso ancho, creo que tienes que usar el MeasureCharacterRanges() método. Aquí está el código de ejemplo utilizando el MeasureString() método para hacer más o menos lo que usted solicitó:

using System;
using System.Collections.Generic; // for List<>
using System.Drawing; // for Graphics and Font

private List<string> GetWordwrapped(string original)
{
    List<string> wordwrapped = new List<string>();

    Graphics graphics = Graphics.FromHwnd(this.Handle);
    Font font = new Font("Arial", 10);

    string currentLine = string.Empty;

    for (int i = 0; i < original.Length; i++)
    {
        char currentChar = original[i];
        currentLine += currentChar;
        if (graphics.MeasureString(currentLine, font).Width > 120)
        {
            // exceeded length, back up to last space
            int moveback = 0;
            while (currentChar != ' ')
            {
                moveback++;
                i--;
                currentChar = original[i];
            }
            string lineToAdd = currentLine.Substring(0, currentLine.Length - moveback);
            wordwrapped.Add(lineToAdd);
            currentLine = string.Empty;
        }
    }

    return wordwrapped;
}

0voto

theJerm Puntos 1521
public static string GetTextWithNewLines(string value = "", int charactersToWrapAt = 35, int maxLength = 250)
        {
            if (string.IsNullOrWhiteSpace(value)) return "";

            value = value.Replace("  ", " ");
            var words = value.Split(' ');
            var sb = new StringBuilder();
            var currString = new StringBuilder();

            foreach (var word in words)
            {
                if (currString.Length + word.Length + 1 < charactersToWrapAt) // The + 1 accounts for spaces
                {
                    sb.AppendFormat(" {0}", word);
                    currString.AppendFormat(" {0}", word);
                }
                else
                {
                    currString.Clear();
                    sb.AppendFormat("{0}{1}", Environment.NewLine, word);
                    currString.AppendFormat(" {0}", word);
                }
            }

            if (sb.Length > maxLength)
            {
                return sb.ToString().Substring(0, maxLength) + " ...";
            }

            return sb.ToString().TrimStart().TrimEnd();
        }

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X