locked
WPF Image Cache / Invalidate Cache RRS feed

  • Question

  • I am pulling what's left of my hair out on this.  I know that Images in WPF are cached if loaded via URI and you can control to a certain extend the behavior using BitmapCachedOption.  But really all I want to do is invalidate the cache of an object whenever that image gets overwritten.

    Scenario:  I have a grid and as the user navigates to a new row, there is a bound control that displays an image.  (using  Source="{Binding MatchedUri}")  This works great until the user changes the image - the new image is written to azure, but because of caching locally, the end user does not see the new image.  I have read in other threads that I can reload the image via a stream,  which does in fact load the new image.  However, the second you do that you break the data binding.  Resetting the binding then just returns the cached image again.  The other alternative seems to be to just not cache at all which is not what I want.  I simply want to invalidate the cache for that single image so it reloads (and I don't want to change the default caching behavior because changing the image is not the norm)  The image does not appear to be written to local disk as I can't find it (even using Uri.LocalPath) so I assume it is in memory.

    Any help would be appreciated.
    BW


    Friday, August 12, 2016 6:24 PM

Answers

  • >>I have read in other threads that I can reload the image via a stream,  which does in fact load the new image.  However, the second you do that you break the data binding.  Resetting the binding then just returns the cached image again. 

    You need to bind to an ImageSource instead of binding to an Uri. Please refer to the following sample code where you can replace the file on disk while the image is being displayed in the UI and you can also switch between two different image files:

    public partial class Window16 : Window, INotifyPropertyChanged
        {
            public Window16()
            {
                InitializeComponent();
                DataContext = this;
                SetSource("Images/1.jpg");
            }
    
            private ImageSource _source;
            public ImageSource Source
            {
                get { return _source; }
                set { _source = value; NotifyPropertyChanged(); }
            }
    
            private void SetSource(string fileName)
            {
                BitmapImage bi = new BitmapImage();
                bi.BeginInit();
                bi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                bi.UriSource = new Uri(fileName, UriKind.RelativeOrAbsolute);
                bi.CacheOption = BitmapCacheOption.OnLoad;
                bi.EndInit();
                Source = bi;
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
    
            private void Button_Click_1(object sender, RoutedEventArgs e)
            {
                File.Copy("Images/1.gif", "Images/temp.gif", true);
                File.Copy("Images/2.gif", "Images/1.gif", true);
                File.Copy("Images/temp.gif", "Images/2.gif", true);
                //refresh binding
                SetSource("Images/1.gif");
            }
        }
    

            <Image Stretch="None" Source="{Binding Source}" />
            
            <Button Content="Replace Image" Click="Button_Click_1" />

    Hope that helps.

    Of course you will need to provide a full runnable sample of what you are trying to do if you want any further help. I am afraid no one will be able to guess how you bind to an navigate between the images.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    • Proposed as answer by DotNet Wang Sunday, August 21, 2016 3:13 AM
    • Marked as answer by DotNet Wang Wednesday, August 24, 2016 1:52 AM
    Saturday, August 13, 2016 5:17 PM