c# - 我的打印 PDF 不显示原始窗口的绑定(bind)数据 - C# MVVM

标签 c# wpf mvvm

我正在尝试使用 MVVM 架构打印我的窗口(打印预览)。到目前为止,我能够将窗口的控件打印到打印中。但它没有显示数据绑定(bind)。

这是我的 PrintPreview.xaml 代码

<ScrollViewer VerticalScrollBarVisibility="Auto">
    <!--Main Grid-->
    <Grid x:Name="MainGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2.5*"/>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="2.5*"/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height ="1.5*"/>
            <RowDefinition Height ="1.7*"/>
            <RowDefinition Height ="5*" MinHeight="200"/>
            <RowDefinition Height ="7*" MinHeight="200"/>
            <RowDefinition Height ="6*" MinHeight="100"/>
            <RowDefinition Height ="2*"/>
        </Grid.RowDefinitions>

        <Grid Grid.RowSpan="2" Grid.ColumnSpan="3" Background="#9dc6a7"/>

        <!--Patient Id block-->
        <StackPanel Grid.ColumnSpan="2" Style="{StaticResource StackpanelStyle}">
            <Label FontSize="16" FontWeight="Bold" Foreground="White">
                Patient ID :
            </Label>
            <Label FontSize="16" Foreground="White" Margin="5,0,0,0" Content="{Binding Path=PatientID}"/> 
        </StackPanel>

        <!--Date block-->
        <StackPanel Grid.ColumnSpan="3" Style="{StaticResource StackpanelStyle}" HorizontalAlignment="Right">
            <Label FontSize="16" FontWeight="Bold" Foreground="White">
                Date :
            </Label>
            <Label Name="date_time" FontSize="16" Foreground="White" Margin="5,0" Content="{Binding Path=CurrentDate}"/>
        </StackPanel>

        <!--Title block-->
        <TextBlock Grid.Row="1" Grid.ColumnSpan="3"  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" FontWeight="Bold" TextDecorations="Underline" Foreground="White">
            Patient Registration Information
        </TextBlock>

        <!--Sub grid 1-->
        <Grid Grid.Row="2" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Stretch" Margin="25,10,25,10">

            <!--User's image View and name-->
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical">
                <Ellipse Width="150" Height="150">
                    <Ellipse.Fill>
                        <ImageBrush x:Name="ImageViewer2" ImageSource="{Binding Path=PatientImageSource}"/>
                    </Ellipse.Fill>
                </Ellipse>
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Margin="0,10">
                    <Label Style="{StaticResource LabelStyles}" Margin="0">Patient Name :</Label>
                    <TextBlock x:Name="ViewName" Style="{StaticResource TextBlockStyle}" Text="{Binding Path = PatientName}"/>
                </StackPanel>
            </StackPanel>
        </Grid>

        <!--Sub grid 2-->
        <GroupBox Grid.Row="3" Grid.ColumnSpan="3" HorizontalAlignment="Stretch"  VerticalAlignment="Center" Margin="25,-35,25,0">
            <GroupBox.Header>
                <TextBlock Style="{StaticResource TextBlockStyleControl}">Patient Personal Information</TextBlock>
            </GroupBox.Header>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="500*"/>
                    <ColumnDefinition Width="500*"/>
                </Grid.ColumnDefinitions>

                <Grid.RowDefinitions>
                    <RowDefinition Height="5*"/>
                    <RowDefinition Height="3*" MaxHeight="80"/>
                </Grid.RowDefinitions>

                <StackPanel Grid.Row="0" Grid.Column="0" Orientation="Vertical" Margin="10,5">
                    <Label Style="{StaticResource PreviewLabelStyles}" >Address :</Label>
                    <TextBlock x:Name="ViewANum"  Style="{StaticResource TextBlockStyle}" Text="{Binding Path =  PatientAddress.Number}"/>
                    <TextBlock x:Name="ViewAStrt" Style="{StaticResource TextBlockStyle}" Text="{Binding Path =  PatientAddress.Street}"/>
                    <TextBlock x:Name="ViewACity" Style="{StaticResource TextBlockStyle}" Text="{Binding Path =  PatientAddress.City}"/>
                </StackPanel>

                <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Vertical" Margin="50,5,10,10">
                    <Label  Style="{StaticResource PreviewLabelStyles}">Gender :</Label>
                    <TextBlock x:Name="ViewGender" Style="{StaticResource TextBlockStyle}" Text="{Binding Path = PatientGender}"/>
                </StackPanel>

                <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Vertical" Margin="10,5">
                    <Label  Style="{StaticResource PreviewLabelStyles}">Date of Birth :</Label>
                    <TextBlock x:Name="ViewDob" Style="{StaticResource TextBlockStyle}" Text="{Binding Path = PatientDateOfBirth}"/>
                </StackPanel>

                <StackPanel Grid.Row="1" Grid.Column="1" Orientation="Vertical" Margin="50,5,10,5">
                    <Label Style="{StaticResource PreviewLabelStyles}">Age :</Label>
                    <TextBlock x:Name="ViewAge" Style="{StaticResource TextBlockStyle}" Text="{Binding Path = PatientAge}"/>
                </StackPanel>
            </Grid>
        </GroupBox>

        <!--Sub grid 3-->
        <GroupBox Grid.Row="4" Grid.ColumnSpan="3" HorizontalAlignment="Stretch"  VerticalAlignment="Center" Margin="25,-25,25,0">
            <GroupBox.Header>
                <TextBlock Style="{StaticResource TextBlockStyleControl}">Patient Medical Information</TextBlock>
            </GroupBox.Header>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="500*"/>
                    <ColumnDefinition Width="500*"/>
                </Grid.ColumnDefinitions>

                <Grid.RowDefinitions>
                    <RowDefinition Height="3*"/>
                    <RowDefinition Height="3*" />
                </Grid.RowDefinitions>

                <StackPanel Grid.Row="0" Grid.Column="0" Orientation="Vertical" Margin="10,5">
                    <Label Style="{StaticResource PreviewLabelStyles}">Department :</Label>
                    <TextBlock x:Name="ViewDepartment" Style="{StaticResource TextBlockStyle}" Text="{Binding Path=PatientDepartment}"/>
                </StackPanel>

                <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Vertical" Margin="50,5,10,0">
                    <Label  Style="{StaticResource PreviewLabelStyles}">Ward :</Label>
                    <TextBlock x:Name="ViewWard" Style="{StaticResource TextBlockStyle}" Text="{Binding Path=PatientWard}"/>
                </StackPanel>

                <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Vertical" Margin="10,5,10,10">
                    <Label  Style="{StaticResource PreviewLabelStyles}">Doctor in Charge :</Label>
                    <TextBlock x:Name="ViewDoc" Style="{StaticResource TextBlockStyle}" Text="{Binding Path=PatientDotorcInCharge}"/>
                </StackPanel>
            </Grid>
        </GroupBox>

        <Button Grid.Row="5" Grid.Column="2" Style="{StaticResource ButtonStyle}" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="20,7,26,0" Content="Print Content" Command="{Binding Path=PrintCommand}"/>

    </Grid>
</ScrollViewer>

这是我的 PrintPreview ViewModel 代码,
class PrintPreviewViewModel
{
    #region Data Members
    private IWindowService m_windowService;
    #endregion

    #region Constructors
    public PrintPreviewViewModel(PatientRecordDetailsModel patient)
    {
        string id = patient.PatientId;

        PatientID = id.PadRight(6).Substring(0, 6);
        PatientName = patient.PatientName;
        PatientAddress = patient.PatientAddress;
        PatientGender = patient.PatientGender;
        PatientDateOfBirth = patient.PatientDateOfBirth.ToShortDateString();
        PatientAge = patient.PatientAge;
        PatientImageSource = patient.PatientImageSource;
        PatientDepartment = patient.PatientDepartment;
        PatientWard = patient.PatientWard;
        PatientDotorcInCharge = patient.PatientDoctorInCharge;

        m_windowService = new WindowService();
    }
    #endregion

    #region Properties
    public string PatientID { get; set; }

    public string PatientName { get; set; }

    public PatientAddress PatientAddress { get; set; }

    public string PatientGender { get; set; }

    public string PatientDateOfBirth { get; set; }

    public int PatientAge { get; set; }

    public ImageSource PatientImageSource { get; set; }

    public string PatientDepartment { get; set; }

    public string PatientWard { get; set; }

    public string PatientDotorcInCharge { get; set; }
    #endregion

    #region <PrintPreview> Members
    public string CurrentDate => m_windowService.GetCurrentDate();
    #endregion

    #region Properties : Commands
    public ICommand PrintCommand
    {
        get => new PatientRecordDetailsCommands(param => OnPrintCommandExecute(), param => OnPrintCommandCanExecute());
    }
    #endregion

    #region Handlers : Commands
    private void OnPrintCommandExecute()
    {
        m_windowService.PrintWindow();
    }

    private bool OnPrintCommandCanExecute()
    {
        return true;
    }
    #endregion

}
}

如您所见,我正在通过服务类从另一个窗口打开 printPreview 窗口。患者对象正在通过它发送。打印按钮命令的实现也在同一个服务类中定义。我使用这种方法来减少 MVVM 违规。
这是我的服务类
   class WindowService : IWindowService
   {

    public void CreateWindow(PatientRecordDetailsModel patient)
    {
        PrintPreview printPreview = new PrintPreview();
        printPreview.DataContext = new PrintPreviewViewModel(patient);
        printPreview.Show();
    }

    public string GetCurrentDate()
    {
        DateTime dateTime = DateTime.Now;

        string date = dateTime.ToString("d");
        string time = dateTime.ToString("T");
        string Date_Time = date + " " + time;

        return Date_Time;
    }

    public void PrintWindow()
    {
        PrintPreview printPreview = new PrintPreview();
        PrintDialog printDlg = new PrintDialog();            
        PrintQueue ReceiptPrinter = new LocalPrintServer().GetPrintQueue("Microsoft Print To PDF");
        PrintCapabilities PC = ReceiptPrinter.GetPrintCapabilities();
        printDlg.PrintQueue = ReceiptPrinter;
        printPreview.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
        Size PreGridSize = printPreview.DesiredSize;
        double Scale = Math.Min(PC.PageImageableArea.ExtentWidth / PreGridSize.Width, PC.PageImageableArea.ExtentHeight / PreGridSize.Height);
        printPreview.LayoutTransform = new System.Windows.Media.ScaleTransform(Scale, Scale);
        Size PaperSize = new Size(PC.PageImageableArea.ExtentWidth, Math.Min(PC.PageImageableArea.ExtentHeight, PreGridSize.Height));
        printPreview.Measure(PaperSize);
        Point ptGrid = new Point(PC.PageImageableArea.OriginWidth, PC.PageImageableArea.OriginHeight);
        printPreview.Arrange(new Rect(ptGrid, PaperSize));

        Application.Current.Dispatcher.BeginInvoke(
            new Action(delegate () { printDlg.PrintVisual(printPreview.MainGrid, "PrintPreview"); }),
            DispatcherPriority.Send);

    }
}

我尝试将患者对象分配给 PrintWindow() 内的数据上下文,但它返回一个空对象。

This is the original printPreview Window

This is how the print looks like

所以我想应该有一个正确的方法来做到这一点。

最佳答案

您的问题是您没有在 PrintWindow 函数中分配 DataContext 。

让我们来看看

    public void PrintWindow()
    {

在这里我们创建一个新的打印预览

        PrintPreview printPreview = new PrintPreview();
        PrintDialog printDlg = new PrintDialog();            
        PrintQueue ReceiptPrinter = new LocalPrintServer().GetPrintQueue("Microsoft Print To PDF");
        PrintCapabilities PC = ReceiptPrinter.GetPrintCapabilities();
        printDlg.PrintQueue = ReceiptPrinter;
        printPreview.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
        Size PreGridSize = printPreview.DesiredSize;
        double Scale = Math.Min(PC.PageImageableArea.ExtentWidth / PreGridSize.Width, PC.PageImageableArea.ExtentHeight / PreGridSize.Height);
        printPreview.LayoutTransform = new System.Windows.Media.ScaleTransform(Scale, Scale);
        Size PaperSize = new Size(PC.PageImageableArea.ExtentWidth, Math.Min(PC.PageImageableArea.ExtentHeight, PreGridSize.Height));
        printPreview.Measure(PaperSize);
        Point ptGrid = new Point(PC.PageImageableArea.OriginWidth, PC.PageImageableArea.OriginHeight);
        printPreview.Arrange(new Rect(ptGrid, PaperSize));

        Application.Current.Dispatcher.BeginInvoke(
            new Action(delegate () { printDlg.PrintVisual(printPreview.MainGrid, "PrintPreview"); }),
            DispatcherPriority.Send);

    }

如您所见,您没有将数据上下文分配给它。实际上,您在其中分配数据上下文的 createiwndow 函数根本不会被调用。

您可以在这里看到打印命令调用 PrintWindow 函数而不是 createwindow。

    #region Properties : Commands
    public ICommand PrintCommand
    {
        get => new PatientRecordDetailsCommands(param => OnPrintCommandExecute(), param => OnPrintCommandCanExecute());
    }
    #endregion

    #region Handlers : Commands
    private void OnPrintCommandExecute()
    {
        m_windowService.PrintWindow();
    }

    private bool OnPrintCommandCanExecute()
    {
        return true;
    }
    #endregion

关于c# - 我的打印 PDF 不显示原始窗口的绑定(bind)数据 - C# MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61223410/

相关文章:

c# - Gtk# 中是否有文件夹浏览器小部件?

mvvm - 在 ZK 框架中使用 MVVM 的奇怪复选框行为

c# - Xamarin.Forms 使用 MVVM 在屏幕之间传输数据

.net - 绑定(bind)到数据网格中的命令

c# - WPF ComboBox 和所选项目出现问题

c# - 遍历站点相对路径以查找文件 (ASP.NET MVC 3)

c# - 在 Reporting Services 2008 webservice 中调用渲染流时出错

c# - 带有 IN 语句的 Oracle 参数?

c# - 通过从 App.xaml 绑定(bind)加载 ResourceDictionary?

c# - 即使内容比容器高,WPF 控件也会对齐到底部