为什么动态加载控件上的数据绑定会中断?
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>
现在应用程序应该根据数据集动态添加 BlockUIContainer
s。我需要在代码隐藏中执行此操作以实现自定义分页,因为报告可能会超过一页。
因为我只需要一个模板文件,所以我将页眉、页脚和分组控件都打包在一个 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
属性.
目前我正在设计一个应用程序,该应用程序应该能够在某一时刻使用数据绑定(涉及 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>
现在应用程序应该根据数据集动态添加 BlockUIContainer
s。我需要在代码隐藏中执行此操作以实现自定义分页,因为报告可能会超过一页。
因为我只需要一个模板文件,所以我将页眉、页脚和分组控件都打包在一个 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
属性.