【问题标题】:Binding a list in a FlowDocument to List<MyClass>?将 FlowDocument 中的列表绑定到 List<MyClass>?
【发布时间】:2011-06-04 16:12:43
【问题描述】:

我有一个 FlowDocument,其中包含绑定到我的 ViewModel 的内容,如下所示:

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

现在我想使用某种 DataTemplate 显示一个类列表,但不知道如何开始。假设我有这样的课程:

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

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

我想将它绑定到 FlowDocument 列表,如下所示:

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

当然这不起作用 - 但我找不到任何解释如何使用模板在 FlowDocument 中绑定列表 - 这可能吗?

【问题讨论】:

    标签: wpf mvvm binding flowdocument


    【解决方案1】:

    this question

    我认为你有两个选择

    • 使用 ItemsControl
    • 使用附加属性

    更新
    使用两个附加属性的更动态的解决方案。带有模板的资源被添加到段落中(必须设置x:Shared="False" 属性,否则我们将一遍又一遍地添加相同的元素)。然后将源列表和模板资源的名称设置为附加属性。

    在 PropertyChanged 回调中,检查是否设置了两个属性,然后为列表中的每个项目创建一个 Span 元素。跨度元素DataContext 设置为当前项以使绑定工作

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

    【讨论】:

    • 我想知道使用这个Flowdocument是否仍然可以混合编辑,这将是可爱的。
    • @Sam:你的意思是想在Paragraph 中添加“Bold”、“Run”等,或者你通常如何在 Blend 中使用 FlowDocument?我从来没有做过:)
    • 我似乎对此解决方案有疑问,特别是在运行附加属性时,尚未填充 Resources 属性,因此没有“inlineTemplate”资源可供查找
    • 如何设置FlowText中部分单词的颜色?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    相关资源
    最近更新 更多