Click here to Skip to main content
16,022,309 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
The WPF sample app requires 2 small images pic1.png and pic2.png in the local folder c:\temp. The app has two buttons that allow you to copy either pic1.png or pic2.png to pic.png.
The Load button is used to display the pic.png file with the WPF image control image1.
The Unload button can be used to remove the display of the image.


The problem:
If, after loading, viewing, and unloading the first image, the second image is copied to pic.png, the first image appears again after the pic.png is reloaded, and not the new content.
Windows file explorer show the correct content after copy to pic.png but not the image1.
What is wrong?

WPF Code:
<Window x:Class="ShowPictureIssue.MainWindow"
        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"        
        mc:Ignorable="d"
        Title="swap picture"
        SizeToContent="WidthAndHeight"
        Topmost="True"
        >
    
    <StackPanel>
        <StackPanel Orientation="Horizontal" Margin="2">
            <Button x:Name="btnLoad" Content="Load fn"  Click="btnLoad_Click" Margin="4" Width="60" Height="20" ToolTip="Load file fn"/>
            <Button x:Name="btnUnload" Content="Unload fn" Click="btnUnload_Click" Margin="4" Width="60" Height="20" ToolTip="Unload image of file fn"/>
            <Button x:Name="btnSetFN1" Content="fn:=fn1" Click="btnSetFN1_Click"  Margin="4" Width="60" Height="20" ToolTip="Copy file fn1 to fn"/>
            <Button x:Name="btnSetFN2" Content="fn:=fn2" Click="btnSetFN2_Click"  Margin="4" Width="60" Height="20" ToolTip="Copy file fn1 to fn"/>
        </StackPanel>

        <Border x:Name="border1" BorderBrush="Black" BorderThickness="1" Margin="2" Padding="2">
            <Image x:Name="image1" Width="256"/>
        </Border>

        <TextBlock x:Name="txtInfo" HorizontalAlignment="Stretch" Height="20" Margin="4" Background="LightYellow"/>
    </StackPanel>
</Window>



Code behind:

C#
using System.IO;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media.Imaging;

namespace ShowPictureIssue
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window
	{
		public MainWindow()
		{
			InitializeComponent();
		}

		string fn1 = @"C:\temp\pic1.png";
		string fn2 = @"C:\temp\pic2.png";
		string? currentFn;
		string Filename = @"C:\temp\pic.png";

		private void btnLoad_Click(object sender, RoutedEventArgs e)
		{
			LoadPic();
		}
		
		/// <summary>
		/// Load the picture from local file Filename into WPF Image control image1
		/// </summary>
		void LoadPic()
		{
			try
			{								
				BitmapImage bmi = new BitmapImage();
				bmi.BeginInit();
				bmi.UriSource = new Uri(Filename, UriKind.Absolute);
				bmi.CacheOption = BitmapCacheOption.OnLoad; 			
				bmi.EndInit();

				bmi.Freeze(); // required to allow copy of a file to fn
				
				image1.Source = bmi;				

				txtInfo.Text = "loaded.";
			}
			catch(Exception ex) 
			{
				txtInfo.Text = ex.Message;
			}
		}


		private void btnUnload_Click(object sender, RoutedEventArgs e)
		{
			// How to unload image1 complete?

			image1.Source = null;			
			txtInfo.Text = "unloaded.";			
		}

		private void image1_SourceUpdated(object sender, DataTransferEventArgs e)
		{
			txtInfo.Text = "SourceUpdated " + DateTime.Now.ToString();
		}

		private void btnSetFN1_Click(object sender, RoutedEventArgs e)
		{
			try
			{
				File.Copy(fn1, Filename, true);
				currentFn = fn1;
				txtInfo.Text = "copied fn1 to fn";
			}
			catch (Exception ex)
			{
				txtInfo.Text = ex.Message;
			}
		}

		private void btnSetFN2_Click(object sender, RoutedEventArgs e)
		{
			try
			{
				File.Copy(fn2, Filename, true);
				currentFn = fn2;
				txtInfo.Text = "copied fn2 to fn";
			}
			catch (Exception ex)
			{
				txtInfo.Text = ex.Message;
			}

		}
	}
}


What I have tried:

- Replace image1 dynamicly in code.
- playing with GC
- sometimes it works after several load and anload operations.
Posted

Rather than using UriSource which appears to be locking in the file, you can use the StreamSource instead. This is a working implementation of that function.
C#
void LoadPic()
{
  try
  {
    BitmapImage bmi = new BitmapImage();
    using Stream stream = new MemoryStream(File.ReadAllBytes(Filename));
    bmi.BeginInit();
    bmi.StreamSource = stream;
    bmi.CacheOption = BitmapCacheOption.OnLoad;
    bmi.EndInit();

    bmi.Freeze(); // required to allow copy of a file to fn
    image1.Source = bmi;

    txtInfo.Text = "loaded.";
  }
  catch (Exception ex)
  {
    txtInfo.Text = ex.Message;
  }
}
 
Share this answer
 
Thank you very much! Thats the solution.
 
Share this answer
 
Comments
Pete O'Hanlon 28-May-24 15:01pm    
You are most welcome.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900