0

As the title states, the image shown in the Image control does not change when changing the image using File.Copy having the same file name as the previous one, like so:

string empDirectory = @"POS\" + empLName + "_" + empFName;
string srcPath = @"C:\path\to\src.png";
string newPath = empDirectory + @"\profile_picture.png";
File.Copy(srcPath, newPath);

I also checked the image in the directory and it was replaced with the new image, but the image shown in the WPF is still the previous one. Even with navigating to other user control then returning just for the sake of refreshing, it still does not change. The only time it will change is when I run the app again.

My default name for the picture is profile_picture.png, so only the image itself changes every time I use it. But if I use this, the image shown of the Image control updates successfully

string empDirectory = @"POS\" + empLName + "_" + empFName;
string srcPath = @"C:\path\to\src.png";
string fileName = System.IO.Path.GetFileName(srcPath);
string newPath = empDirectory + @"\" + fileName;
File.Copy(srcPath, newPath);

As for how I refresh the User Control, I just call it again:

UCContainer.Content = new SomeUserControl();

I'm not really good at explaining, so I hope that I conveyed my problem properly.

EDIT

This is how I change the image source in code-behind:

string path = @"POS\" + empLName + "_" + empFName + @"\profile_picture.png"
BitmapImage img = new BitmapImage();
img.BeginInit();
img.CacheOption = BitmapCacheOption.OnLoad;
img.UriSource = new Uri(AppDomain.CurrentDomain.BaseDirectory + path);
img.EndInit();
imgCtrl.Source = img;

EDIT #3

As per Clemen's guidance, here is the new code:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    if (empPic == "")
    {
        bool defaultPic = true;
        empImgSource=DefineImageSource("images/default_product_img.png", defaultPic);
    } else
    {
        bool defaultPic = false;
        empImgSource = DefineImageSource(empPic, defaultPic);
    }
    imgCtrl.Source = empImgSource;
}
private BitmapImage DefineImageSource(string path, bool defaultPic)
    {
        Bitmap img;
        if (defaultPic)
        {
            img = new BitmapImage(new Uri("pack://application:,,,/" + path));
        } else
        {
            if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + path))
            {
                /*
                img = new BitmapImage();
                using (var stream = new FileStream(AppDomain.CurrentDomain.BaseDirectory + path, FileMode.Open, FileAccess.Read))
                {
                    img.BeginInit();
                    img.CacheOption = BitmapCacheOption.OnLoad;
                    img.StreamSource = stream;
                    img.EndInit();
                }
                */

                img = new BitmapImage();
                img.BeginInit();
                img.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                img.CacheOption = BitmapCacheOption.OnLoad;
                img.UriSource = new Uri(AppDomain.CurrentDomain.BaseDirectory + path);
                img.EndInit();

            } else
            {
                img = new BitmapImage(new Uri("pack://application:,,,/images/default_product_img.png"));
            }
        }
        return img;
    }

The empPic there is from the database, it is the path to the image relative to the project's executable. Even I changed on how the image is retrieved, the problem is still the same. If I use the one with the stream, I can't delete the directory holding the image.

Code on how I change the previous image stored with the new one:

private void btnSave_Click(object sender, RoutedEventArgs e)
    {
        using (SqlConnection conn = new SqlConnection(constr))
        {
            ChangeProfilePicture(conn);
        }
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        string imgPath;
        string defaultPath = "pack://application:,,,/images/default_product_img.png";
        string customPath = AppDomain.CurrentDomain.BaseDirectory + origImgPath;
        imgPath = (origImgPath == "") ? defaultPath : customPath;
        BitmapImage img = new BitmapImage();
        img.BeginInit();
        img.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
        img.CacheOption = BitmapCacheOption.OnLoad;
        img.UriSource = new Uri(imgPath);
        img.EndInit();
        imgImgCon.Source = img;
    }

    private void btnBrowser_Click(object sender, RoutedEventArgs e)
    {
        System.Windows.Forms.OpenFileDialog dlg = new System.Windows.Forms.OpenFileDialog();
        dlg.Multiselect = false;
        dlg.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
        if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            filePath = dlg.FileName;
            ImageSource imgSrc = new BitmapImage(new Uri(filePath));
            imgImgCon.Source = imgSrc;
        }
    }

    private void ChangeProfilePicture(SqlConnection conn)
    {
        string newPath;
        int result;
        string empDirectory = @"POS\" + empLName + "_" + empFName;
        if (filePath == null)
        {
            newPath = origImgPath;
        } else
        {
            string fileName = System.IO.Path.GetFileName(filePath);
            newPath = empDirectory + @"\profile_picture.png";
        }

        string query = "SET NOCOUNT OFF; UPDATE dbo.Employee SET EmployeePhotoPath = @photoPath WHERE EmployeeTableID = @tableID";
        using (SqlCommand cmd = new SqlCommand(query, conn))
        {
            cmd.Parameters.AddWithValue("@photoPath", newPath);
            cmd.Parameters.AddWithValue("@tableID", empTableID);
            conn.Open();
            result = cmd.ExecuteNonQuery();
        }
        if (result == 1)
        {
            if (Directory.Exists("POS"))
            {
                if (Directory.Exists(empDirectory))
                {
                    if (filePath == null)
                    {
                        MessageBox.Show("SUCCESS");
                        origImgPath = filePath;
                        this.Close();
                    } else
                    {
                        if (File.Exists(newPath))
                        {
                            File.Delete(newPath);
                            File.Copy(filePath, newPath);
                            MessageBox.Show("SUCCESS");
                            this.Close();
                        }
                        else
                        {
                            File.Copy(filePath, newPath);
                            MessageBox.Show("SUCCESS");
                            this.Close();
                        }
                    }
                }
            }
        }
    }
Carl Binalla
  • 5,393
  • 5
  • 27
  • 46
  • *but the image shown in the WPF is still the previous one* I see no WPF code except calling a constructor. What really is your WPF code? How should it refresh the content? – Patrick Hofman Feb 22 '17 at 08:32
  • @Clemens I'll try the answer in that question – Carl Binalla Feb 22 '17 at 08:45
  • @CarlJan I've edited the answer, and added a code sample that sets the `BitmapCreateOptions.IgnoreImageCache` flag. – Clemens Feb 22 '17 at 08:46
  • @Clemens After changing the code, I can't delete the directory that holds the image, saying that other process is using it. – Carl Binalla Feb 22 '17 at 08:49
  • You also have to set `BitmapCacheOption.OnLoad`. – Clemens Feb 22 '17 at 08:50
  • I can't find any code in your last edit that actually tries to delete a directory. Which directory are you talking about? – Clemens Feb 22 '17 at 09:10
  • Although I didn't put it, I'm using File.Exist then File.Delete first before File.Copy because I'm using the same file name every time I need to change the image on runtime. My default directory would be @"POS\LastName_FirstName\" – Carl Binalla Feb 22 '17 at 09:14
  • So what are you actually trying to delete, the file or the directory? Show that clearly in your question. Besides that, your code is a mess. Why do you have a nested `if/else` block in the top level `else` block, instead of `if {} else if {} else {}`. Also, `return img` from the `if/else` blocks is odd. Better write a single return statement at the end of the method. – Clemens Feb 22 '17 at 09:17
  • Also note that there are the `Path.Combine()` methods to combine file paths, which is safer than concatenating strings with backslashes. – Clemens Feb 22 '17 at 09:19
  • I'm deleting the directory, but I get the error of the image inside the directory is being used by other process, that's why I used that cache for the image. Wait, I'll edit it – Carl Binalla Feb 22 '17 at 09:20
  • @Clemens `.CreateOptions = BitmapCreateOptions.IgnoreImageCache;` worked for me. The problem is that I haven't put that code to all my BitmapImage. Please post it as an answer so I can accept it. So far I'm now getting what I want, Thank you for the patience – Carl Binalla Feb 22 '17 at 09:40
  • You're welcome. There is no need for an answer, as there is already one for the duplicate question. – Clemens Feb 22 '17 at 10:05

0 Answers0