2011-01-06 21 views
8

Tengo un FlowDocument que contiene material con destino a mis ViewModel como esto:¿Enlazar una lista en un FlowDocument a la lista <MyClass>?

<FlowDocumentReader> 
    <FlowDocument> 
    <Paragraph> 
     <Run Text="{Binding MyTextProperty}"/> 
    </Paragraph> 
    </FlowDocument> 
</FlowDocumentReader> 

Ahora quiero mostrar una lista de clase utilizando algún tipo de DataTemplate, pero tiene ni idea de cómo empezar. Dicen que tengo una clase como:

public MyClass 
{ 
    String Title {get;set;} 
    String FlowText {get;set;} 
} 

public List<MyClass> MyList {get;set;} 

Y me gustaría unir esto a la lista FlowDocument, así:

<FlowDocumentReader> 
    <FlowDocument> 
    <List Items="{Binding MyList}"> 
     <Bold><Run Text="{Binding Title}"/></Bold> 
     <LineBreak/> 
     <Run Text="{Binding FlowText}"/> 
    </Paragraph> 
    </FlowDocument> 
</FlowDocumentReader> 

Por supuesto, esto no funciona - pero no puedo encontrar cualquier explicación sobre cómo enlazar Listas en un FlowDocument usando Plantillas - ¿es esto posible?

Respuesta

6

Ver this question.

yo creo que hay dos opciones

  • El uso de un ItemsControl
  • El uso de un bien embargado

actualización
Una solución más dinámica utilizando dos propiedades adjuntas. Se agrega un Recurso con la Plantilla al Párrafo (que debe tener el atributo x:Shared="False" establecido; de lo contrario, seguiremos agregando los mismos elementos una y otra vez). Luego, la Lista de origen y el nombre del recurso de la plantilla se configuran como propiedades adjuntas.

En la devolución de llamada PropertyChanged, se realiza una comprobación de que ambas propiedades están establecidas y luego se crea un elemento Span para cada elemento de la lista. Los elementos span DataContext se establece en el elemento actual para hacer los enlaces funcionan

<FlowDocumentReader xmlns:Collections="clr-namespace:System.Collections;assembly=mscorlib"> 
    <FlowDocument> 
     <Paragraph behaviors:ParagraphInlineBehavior.ParagraphInlineSource="{Binding MyList}" 
        behaviors:ParagraphInlineBehavior.TemplateResourceName="inlineTemplate"> 
      <Paragraph.Resources> 
       <Collections:ArrayList x:Shared="False" x:Key="inlineTemplate"> 
        <Bold> 
         <Run Text="{Binding Title}"/> 
        </Bold> 
        <LineBreak/> 
        <Run Text="{Binding FlowText}"/> 
        <LineBreak/> 
       </Collections:ArrayList> 
      </Paragraph.Resources> 
     </Paragraph> 
    </FlowDocument> 
</FlowDocumentReader> 

ParagraphInlineBehavior

public class ParagraphInlineBehavior : DependencyObject 
{ 
    public static readonly DependencyProperty TemplateResourceNameProperty = 
     DependencyProperty.RegisterAttached("TemplateResourceName", 
              typeof(string), 
              typeof(ParagraphInlineBehavior), 
              new UIPropertyMetadata(null, OnParagraphInlineChanged)); 
    public static string GetTemplateResourceName(DependencyObject obj) 
    { 
     return (string)obj.GetValue(TemplateResourceNameProperty); 
    } 
    public static void SetTemplateResourceName(DependencyObject obj, string value) 
    { 
     obj.SetValue(TemplateResourceNameProperty, value); 
    } 

    public static readonly DependencyProperty ParagraphInlineSourceProperty = 
     DependencyProperty.RegisterAttached("ParagraphInlineSource", 
              typeof(IEnumerable), 
              typeof(ParagraphInlineBehavior), 
              new UIPropertyMetadata(null, OnParagraphInlineChanged)); 
    public static IEnumerable GetParagraphInlineSource(DependencyObject obj) 
    { 
     return (IEnumerable)obj.GetValue(ParagraphInlineSourceProperty); 
    } 
    public static void SetParagraphInlineSource(DependencyObject obj, IEnumerable value) 
    { 
     obj.SetValue(ParagraphInlineSourceProperty, value); 
    } 

    private static void OnParagraphInlineChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     Paragraph paragraph = d as Paragraph; 
     IEnumerable inlines = ParagraphInlineBehavior.GetParagraphInlineSource(paragraph); 
     string templateName = ParagraphInlineBehavior.GetTemplateResourceName(paragraph); 
     if (inlines != null && templateName != null) 
     { 
      paragraph.Inlines.Clear(); 
      foreach (var inline in inlines) 
      { 
       ArrayList templateList = paragraph.FindResource(templateName) as ArrayList; 
       Span span = new Span(); 
       span.DataContext = inline; 
       foreach (var templateInline in templateList) 
       { 
        span.Inlines.Add(templateInline as Inline); 
       } 
       paragraph.Inlines.Add(span); 
      } 
     } 
    } 
} 
+0

Me pregunto si se utiliza esta la FlowDocument puede todavía editado en la mezcla, lo que sería precioso. – Sam

+0

@Sam: ¿Quiere decir agregar "Negrita", "Ejecutar", etc. al "Párrafo" o cómo suele trabajar con un "FlowDocument" en Blend? Nunca lo he hecho :) –

+1

Parece que tengo problemas con esta solución, específicamente cuando se ejecutan las propiedades adjuntas, la propiedad Resources aún no se ha rellenado, por lo que no hay un recurso "inlineTemplate" para buscar –

Cuestiones relacionadas