近日做项目时需要用到简单的WPF打印功能,需要打印的页面上有一个Image控件,调试代码的时候可以正常显示图片,但是我离开了调试,直接运行程序,Image中的图片一直显示不出来,网上搜索了很多相关问题,也向chatGPT问了很久都没有办法定位到问题,最后阴差阳错的给我发现了端倪。
框架是.NET6
先上代码:
1.我建了一个WPF类库,里面有一个WPF窗体:MainWindow.xaml
前端代码:
<Window x:Class="PrintWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" SizeToContent="WidthAndHeight" Height="700" Width="794" Loaded="Window_Loaded">
<Grid>
<Canvas x:Name="printArea" Height="600" Width="794">
<Image x:Name="IDCardPhoto" Width="204" Height="321" Margin="458,0,0,0"/>
</Canvas>
</Grid>
</Window>
后端代码:
using ...略
namespace PrintWpf
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private string imagePath = string.Empty;
private string returnStr = string.Empty;
public MainWindow(string path)
{
InitializeComponent();
imagePath = path;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WinPosition();
ConvertFilePathToBitmapImage();
PrintDialog printDialog = new PrintDialog();
if (printDialog.ShowDialog() == true)
{
printDialog.PrintVisual(printArea, "Print Window");
returnStr = "complete";
this.Close();
}
else
{
returnStr = "cancel";
this.Close();
}
}
/// <summary>
/// 修改窗体初始显示位置
/// </summary>
private void WinPosition()
{
double ScreenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;//WPF
this.Top = this.ActualWidth / 5;
this.Left = ScreenWidth - this.ActualWidth * 1.3;
}
/// <summary>
/// windows文件绝对路径转化为WPF中Image控件的source属性
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public void ConvertFilePathToBitmapImage()
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = new MemoryStream(File.ReadAllBytes(imagePath));
bitmapImage.EndInit();
bitmapImage.Freeze();
IDCardPhoto.Source = bitmapImage;
}
public string ShowDia()
{
this.ShowDialog();
return returnStr;
}
}
}
2.我建了一个winform项目,在里面调用上述的WPF窗体
string source = "图片来源(绝对路径)";
MainWindow mainWindow = new MainWindow(source);
string str = mainWindow.ShowDia();
if (str == "complete")
{
MessageBox.Show("启动打印");
}
else
{
MessageBox.Show("不启动打印");
}
以上代码在我调试的时候,能正常显示出图片内容并打印无误,但是当我直接运行Debug里的程序时,图片就无法显示了,后来发现是我写的有问题,PrintDialog的调用放在了Window_Loaded里面导致图片还没完成加载就占用了窗体资源,导致无法显示图片。
于是我对上述代码做了一些修改,把PrintDialog的调用移出来
前端代码:(添加了一个打印按钮)
<Window x:Class="PrintWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" SizeToContent="WidthAndHeight" Height="700" Width="794" Loaded="Window_Loaded">
<Grid>
<Button Content="打印" Canvas.Left="9" HorizontalAlignment="Left" VerticalAlignment="Top" Height="39" Width="92" Click="Button_Click"/>
<Canvas x:Name="printArea" Height="600" Width="794">
<Image x:Name="IDCardPhoto" Width="204" Height="321" Margin="458,0,0,0"/>
</Canvas>
</Grid>
</Window>
后端代码:(把PrintDialog的调用放到按钮事件中)
using ...略
namespace PrintWpf
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private string imagePath = string.Empty;
private string returnStr = string.Empty;
public MainWindow(string path)
{
InitializeComponent();
imagePath = path;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WinPosition();
ConvertFilePathToBitmapImage();
}
/// <summary>
/// 修改窗体初始显示位置
/// </summary>
private void WinPosition()
{
double ScreenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;//WPF
this.Top = this.ActualWidth / 5;
this.Left = ScreenWidth - this.ActualWidth * 1.3;
}
/// <summary>
/// windows文件绝对路径转化为WPF中Image控件的source属性
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public void ConvertFilePathToBitmapImage()
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = new MemoryStream(File.ReadAllBytes(imagePath));
bitmapImage.EndInit();
bitmapImage.Freeze();
IDCardPhoto.Source = bitmapImage;
}
public string ShowDia()
{
this.ShowDialog();
return returnStr;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
PrintDialog printDialog = new PrintDialog();
if (printDialog.ShowDialog() == true)
{
printDialog.PrintVisual(printArea, "Print Window");
returnStr = "complete";
this.Close();
}
else
{
returnStr = "cancel";
this.Close();
}
}
}
}
这下图片加载跟打印分成了两部分,互不冲突,能正常显示图片和实现打印了。
这两天还搜到一些其他关于WPF Image控件不显示图片的问题回答,
有的说路径不对的,
有的说要把图片引入到项目中,并右键属性设置为资源的,这里就不展开说了,因为我的图片不是固定资源,是实时读取别的地方的文件。
ok,希望能帮到你。