WPF: Visual Studio 2008 设计器中的 FixedDocument

11

在XAML中构造FixedDocument时,Visual Studio会显示错误,这是一个众所周知的漏洞。例如,以下代码片段:

<DocumentViewer>
    <FixedDocument>
        <PageContent>
            <FixedPage Width="21.0cm" Height="29.7cm">
                <TextBlock>Hello World!</TextBlock>
            </FixedPage>
        </PageContent>
    </FixedDocument>
</DocumentViewer>

编译和运行都很好,但Visual Studio在错误列表中显示一个错误(属性“Pages”不支持类型为“PageContent”的值。),这很烦人。
我正在寻找一种解决方案,允许我在Visual Studio的XAML文件中构建文档,而不会出现该错误消息。我已经找到了一种解决方法,我想在下面作为答案分享,但我很好奇是否有更好(更优雅)的解决方案。
4个回答

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

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>

3

更加简洁的解决方案:

[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类的命名空间。

这也可以启用文档的设计时预览。


请注意,这会破坏打印功能:https://dev59.com/0Y7ea4cB1Zd3GeqPHuxQ - hillin
我回答了那个问题,并修复了打印功能的故障。 - Mike Nakis

1

我在处理固定文档时遇到了同样的问题。我认为这可能比其他人建议的方法更加干净的解决方法。

基本上,你应该创建一个从FixedDocument派生的自定义类,就像hillin建议的那样,并添加一个属性来获取此对象的PageContents中的FixedDocument。但是由于这些页面现在是另一个对象的可视子对象,所以你应该使用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的静态资源,并将您的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>

现在这两个问题都得到了解决。具有实时设计预览且没有编译错误,并且输出可以打印。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接