2010-01-28 9 views
6

Tenemos una aplicación WPF que muestra texto que contiene los diversos símbolos corporativos; como marca comercial, marca registrada, derechos de autor y marca de servicio.Cómo insertar derechos de autor, marca registrada, marca de servicio, etc. en el cuadro de texto WPF cuando la fuente no admite símbolos

La base de datos tiene algunos campos que incluyen los símbolos corporativos estándar. Inicialmente, los datos se marca como sigue:

Example Corp(TM) or Example Plan (SM)

podemos cambiar fácilmente los marcadores de posición a sus respectivos equivalentes en Unicode; y de hecho tiene en la mayoría de los casos.

El problema que tenemos es que la fuente utilizada por la aplicación no es compatible con el símbolo de la marca de servicio (que es simplemente un superíndice SM). Lo más probable es que no podamos reemplazar la fuente o editarla.

Los campos pueden ser un nombre de producto simple con el símbolo al final, o una descripción larga con un símbolo que figura 0 o más veces. Vinculamos TextBoxes o Labels directamente a un ViewModel y/o al objeto comercial (generalmente a través de DataTemplates). Todos los datos en la aplicación son de solo lectura.

Por lo tanto, suponiendo que tenemos que abordar este código de vía (en C# y WPF), ¿cuáles son mis opciones?

+0

¿Puede decirnos más sobre esta fuente (nombre? Propio o comercial?) Y ¿por qué no puede usar una fuente diferente? –

+0

Es una fuente interna personalizada; no puede usar uno diferente porque debería pasar por un largo proceso de aprobación. El cliente es muy grande, y creo que tendríamos problemas para rastrear quién lo creó. – SergioL

Respuesta

4

Editar: He descubierto en una respuesta diferente que el TextBlock también tiene una colección Inlines a la que se puede agregar Run s. Anvaka's answer ingeniosamente utiliza una propiedad adjunta como una especie de convertidor.


Tuve algunas ideas sobre cómo abordar esto. Solo uno manejaría el ajuste de palabras correctamente y manejaría ejecuciones de caracteres con diferentes fuentes.

Usa un FlowDocumentScrollViewer y ata la cuerda con un ValueConverter que convierte la cadena en FlowDocument.

<FlowDocumentScrollViewer 
    HorizontalScrollBarVisibility="Hidden" 
    VerticalScrollBarVisibility="Hidden" 
    Document="{Binding MyString, Converter={StaticResource MyConverter}}" /> 

Puede crear propiedades en el convertidor para establecer las propiedades de letra normal, que no pueden ser establecidas en la FlowDocumentScrollViewer y tiene que ser establecido en el FlowDocument que crea el convertidor. Probablemente también necesite algunas propiedades de Fuente para las subcadenas de excepción que necesitan una Fuente diferente (y posiblemente un tamaño diferente). Otra opción es crear Binding s en el FlowDocument para algunas de esas propiedades (RelativeSource).

Y así es como se crea un FlowDocument en código:

FlowDocument doc = new FlowDocument(); 
doc.FontFamily = new FontFamily("Our Own Font"); 
Paragraph par = new Paragraph(); 
doc.Blocks.Add(par); 

A continuación, tendrá que dividir la cadena entrante en las subseries especiales, manteniendo intactas las subcadenas. Tendrá que hacer rodar su propio divisor y tener una colección de subcadenas en el convertidor o ser suministradas al convertidor.

Añadir una subcadena normal al párrafo:

Run r = new Run(substring); 
par.Inlines.Add(r); 

Añadir una subcadena especial al párrafo con una fuente diferente:

Run r = new Run(substring); 
r.FontFamily = new FontFamily("Arial"); 
par.Inlines.Add(r); 

Los anteriores son sólo pequeños fragmentos. No sé cómo quieres acercarte a dividir la cadena o iterar sobre las subcadenas ya que no estoy familiarizado con los datos, así que no proporcioné el método que utilicé solo para ver si mi idea funcionaría. También puede usar Dictionary para detectar una subcadena y usar un reemplazo en la salida, como detectar "(SM)" y reemplazarlo por "℠".

Deseo saber si tiene alguna pregunta o si hay algo que pueda detallar.

(Es bueno que usted ha dicho que es de sólo lectura. Un RichTextBox no funcionaría porque su propiedad Document no es un DependencyProperty y por lo tanto no puede ser el objetivo de un Binding. Aunque, uno puede ser capaz de utilizar Mode=OneWayToSource revertirla, la implementación de ConvertBack en lugar de Convert.)


"creo que lo que dejó fuera (iteración en la cadena y la creación de esas carreras) es la parte difícil."

De hecho, fui muy breve sobre la división de la secuencia en las subcadenas especiales. Cuando dije: "No sé cómo dividirás la cadena", no estaba diciendo que no tenía ni idea de cómo hacerlo (lo reformulé), pero que no tenía idea de cómo querrías. para manejarlo Supuse que no sería difícil para usted descifrar esa parte porque es el tipo de problema de manipulación de cuerdas que los posibles contratistas averiguarían. Eso, y es posible que descubras casos límite entre tus datos que requieren cambios en la forma en que lo manejas.

Le describiré una versión relativamente cruda utilizando IndexOf() y Substring().

Así que aquí está el problema-dentro-del-problema: tiene muchas cadenas (por ejemplo, "Company Name(R), makers of Product(TM)") que contienen 0 o más subcadenas especiales. Estas subcadenas son pocas y conocidas, y la cadena de entrada debe dividirse en varias cadenas donde las subcadenas especial y no especial se han aislado una de otra (por ejemplo, {"Company Name", "(R)", ", makers of Product", "(TM)"}).

Las subcadenas especiales son pocas y conocidas, por lo que necesita una serie de ellas. Usted sabe por el valor de retorno de .IndexOf() si encontró una subcadena o no. Al recorrer las subcadenas especiales conocidas, puede encontrar la primera instancia de cualquiera de ellas con una comparación de índices, también dejando de lado la longitud de la subcadena.

Cada vez que se encuentre la subcadena más temprano especial en la cadena S (si lo hay), se hace derivar cadenas A, B y C. B es la subcadena especial, A y C son el antes y el después. Adjunte A y B a List y C se convierte en el nuevo S y lo vuelve a hacer. Excepto cuando no encuentre ninguna subcadena especial en S y no esté vacía, en cuyo caso solo la adjuntará.

Ahora, cada cadena de índice impar en List es una subcadena especial. Es posible que desee consultar mi mención de un Dictionary en la parte anterior de esta respuesta para usar como una búsqueda para agregar un Run de "℠" cuando la subcadena que encontró fue "(SM)".

+0

Romper el texto en Elementos de ejecución es probablemente el camino a seguir; sin embargo, eso es solo parte de la solución. Creo que lo que dejaste fuera (iterar sobre la cuerda y crear esas Runs) es la parte difícil. – SergioL

+0

Voy a marcar esto como la respuesta correcta, a pesar de que esperaba algo un poco más elegante. En realidad, fue una combinación de la respuesta de Anvaka y la manipulación de la cadena de fuerza bruta que terminé implementando. – SergioL

+0

Me parece bien. En mi opinión, separar las cuerdas siempre es poco elegante. Lo único que lo arreglaría, simplemente transfiriendo la complejidad de un lugar a otro, sería separar la cadena con Regex. –

1

Si su elemento de visualización es compatible con varias fuentes como un control RichTextbox, puede formatear la cadena con las fuentes adecuadas alrededor de los símbolos (TM) y (SM).

+0

Creo que acaba de replantear el problema. – SergioL

0

Una forma un tanto desagradable de hacerlo, pero una opción podría ser colocar pequeñas imágenes que contengan el símbolo pre-renderizado en lugares apropiados. Dado que los datos no son estáticos (si lo entiendo correctamente), necesitaría calcular la posición de las imágenes dinámicamente, lo que sería difícil a menos que la fuente sea de ancho fijo.

Cuestiones relacionadas