2012-02-10 20 views
41

Tengo un texto en un RichTextBox. Este texto incluye etiquetas, por ejemplo: [@TagName!]. Quiero reemplazar estas etiquetas con algunos datos de una base de datos sin perder el formato (fuentes, colores, imágenes, etc.). Creé un método:Reemplazar texto en XamlPackage

void ReplaceTagsWithData(FlowDocument doc) 
    { 
     FileStream fs = new FileStream("tmp.xml", FileMode.Create); 
     TextRange trTextRange = 
      new TextRange(doc.ContentStart, doc.ContentEnd); 

     trTextRange.Save(fs, DataFormats.Xaml); 
     fs.Dispose(); 
     fs.Close(); 

     StreamReader sr = new StreamReader("tmp.xml"); 

     string rtbContent = sr.ReadToEnd(); 

     MatchCollection mColl = 
      Regex.Matches(rtbContent, 
          string.Format(@"\{0}+[a-zA-Z]+{1}", 
          prefix, 
          postfix)); 

     foreach (Match m in mColl) 
     { 
      string colname = 
       m.Value.Substring(prefix.Length, 
        (int)(m.Value.Length - (prefix.Length + postfix.Length))); 

      rtbContent = rtbContent.Replace(m.Value.ToString(), 
              dt.Rows[0][colname].ToString()); 
     } 

     rtbEdit.Document = 
      new FlowDocument(
       (Section)XamlReader.Load(
        XmlReader.Create(new StringReader(rtbContent)))); 
     sr.Dispose(); 
     sr.Close(); 
    } 

Es bastante bueno, pero elimina las imágenes del contenido. Sé que debería usar XamlPackage en lugar de Xaml, pero no puedo obtenerlo como texto sin formato. ¿Hay alguna otra solución para esto?

Gracias por responder. ;)

[EDIT: 13/02/2012 02:14 (am)]

Mi solución de trabajo:

void ReplaceTagsWithData(RichTextBox rtb) 
{ 
    FlowDocument doc = rtb.Document; 

    FileStream fs = new FileStream("tmp", FileMode.Create); 
    TextRange trTextRange = new TextRange(doc.ContentStart, doc.ContentEnd); 
    trTextRange.Save(fs, DataFormats.Rtf); 
    fs.Dispose(); 
    fs.Close(); 

    StreamReader sr = new StreamReader("tmp"); 
    string rtbContent = sr.ReadToEnd(); 
    sr.Dispose(); 
    sr.Close(); 

    MatchCollection mColl = 
     Regex.Matches(rtbContent, 
         string.Format(@"\{0}+[a-zA-Z]+{1}", 
         prefix, 
         postfix)); 

    foreach (Match m in mColl) 
    { 
     string colname = 
      m.Value.Substring(prefix.Length, 
       (int)(m.Value.Length - (prefix.Length + postfix.Length))); 

     rtbContent = rtbContent.Replace(m.Value.ToString(), 
             dt.Rows[0][colname].ToString()); 
    } 
    MemoryStream stream = 
     new MemoryStream(ASCIIEncoding.Default.GetBytes(rtbContent)); 
    rtb.SelectAll(); 
    rtb.Selection.Load(stream, DataFormats.Rtf); 

} 

tal vez no es la mejor, pero está funcionando correctamente.

Fue resuelto. Pero no puedo publicar la solución porque está en el servidor de la compañía al que ya no puedo acceder.

+0

Creo que te refieres a XMLPackage en lugar de XML. Donde pierde la imagen, ¿encuentra una coincidencia en colname de dt.Rows [0] [colname]? – Paparazzi

+0

No. dt.Rows [0] [colname] me da solo nombres de columnas de la base de datos. Las imágenes se agregan en RichTextBox por usuario. – arche89

+0

debido a las múltiples entradas de colname, necesitaría un bucle en algún lugar, por lo que incluso si usara regex.replace en lugar de match, aún tendría que recorrer las columnas, y puede terminar ejecutando reemplazos inútiles debido a los datos eso no necesita correr Eso hace que, en mi opinión, esta sea probablemente la mejor respuesta posible. Obtenga las coincidencias, luego reemplace los datos según sea necesario. – Nevyn

Respuesta

1

Puede utilizar la maquinilla de afeitar del motor para hacer lo que desee en el tema de plantillas completas. Puede descargar desde nuget (http://www.nuget.org/packages/RazorEngine) y sin ninguna configuración de configuración puede usar la sintaxis de Razor para hacerlo. Por ejemplo, su plantilla puede ser la siguiente:

<Window x:Class="<class>" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="@Model.Title" 
     Icon="@Model.Icon"> 
    <Grid>  
    </Grid> 
</Window> 

Nota: la eso de Model.Title @ y @ Model.Icon provienen de la maquinilla de afeitar

En realidad yo uso RazorEngine a toda mi tarea de plantillas: correo electrónico, generación de informes on the fly (rdlc), etc ...

0

La Regex que está utilizando es codiciosa, por lo que coincidiría con todo, desde el inicio de un token hasta el siguiente. Cámbielo a @"\{0}[a-zA-Z]+?{1}" para una mejor coincidencia.

Además, usar la sobrecarga de Regex.Replace que toma una lambda sería un código más limpio.

Cuestiones relacionadas