当您尝试在XAML中构造FixedDocument
时,Visual Studio会显示错误a well-known bug。例如,以下代码段
<DocumentViewer>
<FixedDocument>
<PageContent>
<FixedPage Width="21.0cm" Height="29.7cm">
<TextBlock>Hello World!</TextBlock>
</FixedPage>
</PageContent>
</FixedDocument>
</DocumentViewer>
编译并运行完全正常,但Visual Studio在错误列表中显示错误(Property 'Pages' does not support values of type 'PageContent'.
)这非常烦人。
我正在寻找一种解决方案,允许我在Visual Studio中的XAML文件中构建我的文档而不会收到该错误消息。我找到了一个解决方法,我想在下面分享作为答案,但我很好奇是否有一个更好(更优雅)的解决方案。
答案 0 :(得分:4)
作为一种解决方法,我将DocumentViewer和页面放在一起 进入一个网格:
<Grid>
<FixedPage Width="21.0cm" Height="29.7cm" x:Name="uiPage1">
<TextBlock>Hello World!</TextBlock>
</FixedPage>
<DocumentViewer>
<FixedDocument x:Name="uiReport">
</FixedDocument>
</DocumentViewer>
</Grid>
然后我将页面附加到Loaded
中的DocumentViewer
窗口事件:
VB示例:
DirectCast(Me.uiPage1.Parent, Grid).Children.Remove(Me.uiPage1)
Dim content As New PageContent()
DirectCast(content, IAddChild).AddChild(Me.uiPage1)
Me.uiReport.Pages.Add(content)
C#示例:
((Grid)uiPage1.Parent).Children.Remove(uiPage1);
var content = new PageContent();
((IAddChild)content).AddChild(uiPage1);
uiReport.Pages.Add(content);
答案 1 :(得分:3)
我知道这已经得到了解答,但我认为这个答案更好,因为它不需要你添加DocumentView。
如果有办法通过密钥名称引用资源并将它们放在带有XAML的FixedDocument中,请告诉我。我似乎找不到办法做到这一点,但也许这是可能的。
使用:
var doc = System.Windows.Application.LoadComponent(new Uri("/FixedDocumentExample.xaml", UriKind.Relative)) as FixedDocument;
doc.AddPages();
扩展方法:
using System.Collections;
using System.Windows.Documents;
public static class FixedDocumentExtended {
public static void AddPages(this FixedDocument fixedDocument) {
var enumerator = fixedDocument.Resources.GetEnumerator();
while (enumerator.MoveNext()) {
var pageContent = ((DictionaryEntry)enumerator.Current).Value as PageContent;
if (pageContent != null) {
fixedDocument.Pages.Add(pageContent);
}
}
}
}
XAML:
<FixedDocument
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<FixedDocument.Resources>
<PageContent x:Key="page1">
<FixedPage Width="793.76" Height="1122.56">
<TextBlock Margin="50" Text="Page 1"/>
</FixedPage>
</PageContent>
<PageContent x:Key="page2">
<FixedPage Width="793.76" Height="1122.56">
<TextBlock Margin="50" Text="Page 2"/>
</FixedPage>
</PageContent>
</FixedDocument.Resources>
</FixedDocument>
答案 2 :(得分:1)
更清洁的解决方法:
[ContentProperty("Pages")]
public class XamlFixedDocument : FixedDocument
{
private ObservableCollection<PageContent> _pages;
public XamlFixedDocument()
{
this.Pages = new ObservableCollection<PageContent>();
}
public new ObservableCollection<PageContent> Pages
{
get => _pages;
set
{
_pages = value;
foreach (var page in _pages)
{
base.Pages.Add(page);
}
_pages.CollectionChanged += (o, e) =>
{
if (e.NewItems != null)
{
foreach (PageContent page in e.NewItems)
{
base.Pages.Add(page);
}
}
};
}
}
}
这个FixedDocument
的子类伪造了Pages
属性,并将所有添加的页面重定向到其基类中的真实Pages
属性。
用法:
<doc:XamlFixedDocument xmlns:doc="clr-namespace:Hillinworks.WPF.Document">
<PageContent>
<FixedPage Background="White">
<TextBlock Text="hello, world" />
</FixedPage>
</PageContent>
</doc:XamlFixedDocument>
将Hillinworks.WPF.Document
更改为XamlFixedDocument
类所在的名称空间。
这还可以在设计时预览文档。
答案 3 :(得分:0)
所以我搞砸了固定文档,遇到了同样的问题。而且我认为这可能甚至比其他人建议的解决方案更清洁。
因此,基本上,您应该按照建议hillin创建一个从FixedDocument
派生的自定义类,并添加一个属性以从该对象的FixedDocument
中获取PageContents
。但是由于这些页面现在是另一个对象的可视子级,因此您应该使用XmlReader和XmlWriter类对其进行复制。
[ContentProperty("Pages")]
public class CustomFixedDocument : FixedDocument
{
private ObservableCollection<PageContent> _pages;
public CustomFixedDocument()
{
this.Pages = new ObservableCollection<PageContent>();
}
public FixedDocument FixedDocument
{
get
{
var document = new FixedDocument();
foreach (var p in Pages)
{
var copy = XamlReader.Parse(XamlWriter.Save(p)) as PageContent;
document.Pages.Add(copy);
}
return document;
}
}
public new ObservableCollection<PageContent> Pages
{
get => _pages;
set
{
_pages = value;
foreach (var page in _pages)
{
base.Pages.Add(page);
}
_pages.CollectionChanged += (o, e) =>
{
if (e.NewItems != null)
{
foreach (PageContent page in e.NewItems)
{
base.Pages.Add(page);
}
}
};
}
}
}
现在在xaml中,您可以轻松创建一个CustomFixedDocument
StaticResource并将您的DocumentViewer
绑定到它的'FixedDocument'属性。
<Window x:Class="MyProject.DocumentWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyProject"
mc:Ignorable="d"
Title="DocumentWindow" Height="450" Width="800" Loaded="Window_Loaded">
<Window.Resources>
<local:CustomFixedDocument x:Key="Report">
<PageContent>
<FixedPage Width="793.76" Height="1122.56">
<TextBlock Margin="50" Text="Page 1"/>
</FixedPage>
</PageContent>
<PageContent>
<FixedPage Width="793.76" Height="1122.56">
<TextBlock Margin="50" Text="Page 2"/>
</FixedPage>
</PageContent>
</local:CustomFixedDocument>
</Window.Resources>
<Grid>
<DocumentViewer x:Name="viewer" Document="{Binding Source={StaticResource Report}, Path=FixedDocument}"/>
</Grid>
现在两个问题都已解决。实时设计时预览,没有编译错误,并且可以打印输出。