为什么动态加载控件上的数据绑定会中断?

Why does data binding on a dynamically loaded control break?

目前我正在设计一个应用程序,该应用程序应该能够在某一时刻使用数据绑定(涉及 FlowDocument)从 Xaml 模板文件创建报告。

我们的想法是简单地将通过 BlockUIContainer 动态加载的控件转换为可在 FlowDocument 中打印。

只要我将整个文件加载到一个 FrameworkElement 中并设置 DataContext 属性,数据绑定就像一个魅力。

foreach (Order order in orders)
{
    BlockUIContainer container = new BlockUIContainer();
    container.Child = (FrameworkElement)GetOrderControl();
    (container.Child as FrameworkElement).DataContext = order;
    document.Blocks.Add(container);
}
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.SystemIdle,
    new Action(() => { return; }));

所有 GetOrderControl() 方法所做的都是从 FileStream 中读取并通过 XamlReader.Load() 解析内容。该文件的结构如下:

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    ...
    <TextBlock Text="{Binding Path=Country}" />
    ...
</Gird>

现在应用程序应该根据数据集动态添加 BlockUIContainers。我需要在代码隐藏中执行此操作以实现自定义分页,因为报告可能会超过一页。

因为我只需要一个模板文件,所以我将页眉、页脚和分组控件都打包在一个 xaml 文件中,如下所示:

<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <BlockUIContainer Name="PageHeader">
        <Grid ... />
    </BlockUIContainer>
    <BlockUIContainer Name="Element">
        <Grid ... />
    </BlockUIContainer>
</FlowDocument>

名为 BlockUIContainer 的 "Element" 中的 <Grid ... /> 控件正是之前示例中使用的 Grid 控件。

现在我所做的就是获取 BlockUIContainer 的子项并通过将其保存到字符串并返回到 FrameworkElement 并设置 DataContext.[=30= 来创建它的副本]

foreach (Order order in orders)
{
    BlockUIContainer container = new BlockUIContainer();
    container.Child = (FrameworkElement)XamlReader.Parse(XamlWriter.Save(elementControl));
    (container.Child as FrameworkElement).DataContext = order;
    document.Blocks.Add(container);
}
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.SystemIdle,
    new Action(() => { return; }));

然而,这里的数据绑定没有计算。在设置 DataContext 后,我尝试在 FrameworkElement 上调用 UpdateLayout() 方法。 这确实至少评估了 <DataTrigger Binding="{Binding Path=DangerousGoods}" /> 中的一些绑定,用于设置某些子控件可见性的 <Style> 元素,但未评估 none 之类的绑定,例如 <TextBlock Text="{Binding Path=Country}" />

我在这里不知所措。解析后如何让剩余的绑定再次工作?我真的不想为一个文档创建多个文件。

没关系,我发现了错误...第一次创建控件时会评估绑定。 XamlWriter 然后 "destroys" 绑定,方法是评估文本并将原始文本输出(为空)写入元素的 Text 属性.