2

I have a GridView in my app that basically contains images as following:

<GridView x:Name="ImageGridView">
    <Image x:Name="Image_1"/>
    <Image x:Name="Image_2"/>
    <Image x:Name="Image_3"/>
</GridView>

with this in codebehind for the images to Load:

public void SetImages()
{
  StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
  Image_1.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_1.png"));
  Image_1.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_2.png"));
  Image_1.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_3.png"));
}

The GridView shows the images just fine. However, I also have a Class that changes the colors of those Pictures based on existing values as fallowing:

Changing the Images Colors

This means that the Images sources don't change, and the paths to those images also remain as it is. The only thing changing are the colors in those images as demonstrated in the pictures.

However, when the colors-changing task is finished and the images are updated in the App's LocalState folder, they are not updated in the GridView images.

Ithe Images are not updated in the UI

I have also tried creating an observable collection with the images in question. Binded the GridView to this collection, and at each color update I would include this:

GridView.ItemsSource = null;
GridView.ItemsSource = ImagesCollection;

It would work by changing some Images but not others. this happens randomly. If there it a way to await the first before executing the second, this might work out!

The question is: how to I ask the GridView to reload its content? Update its content? clear cache and re-fetch the Images?

Asem Khen
  • 317
  • 3
  • 15

3 Answers3

0

Put this code into a method:

public void SetImages()
{
    StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    Image_1.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_1.png"));
    Image_2.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_2.png"));
    Image_3.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_3.png"));
}

Call this method once at the beginning and when you modified the images.

horotab
  • 675
  • 3
  • 20
  • I have tried that. I have added a GIF showing that. – Asem Khen Aug 30 '18 at 12:16
  • Can you post the code that is executed when clicking a color? – horotab Aug 30 '18 at 12:29
  • Sure can do! [This is the code](https://www.codepile.net/pile/vY4l59YX) I am using. I patched it from different sources. The colors used are taken from the app settings as #HEX and converted to ARGB – Asem Khen Aug 30 '18 at 14:15
0

Don't be afraid to use MVVM. In your xaml bind the image sources to properties in your viewmodel.

XAML:

<GridView>
    <Image Source="{Binding ImageSource1}"/>
    <Image Source="{Binding ImageSource2}"/>
</GridView>

ViewModel:

public string ImageSource1 => Windows.Storage.ApplicationData.Current.LocalFolder + "/Image_1.png";

public string ImageSource2 => Windows.Storage.ApplicationData.Current.LocalFolder + "/Image_2.png";

// invoke the NotifyPropertyChanged event to enforce an update.
public void UpdateImages()  {
    InvokePropertyChanged(nameof(ImageSource1));
    InvokePropertyChanged(nameof(ImageSource2));
}
ChristianMurschall
  • 1,621
  • 15
  • 26
  • 1
    What if there are `n` no of images? Instead of creating Properties for each `Image`, It should be a `IReadonlyList`. Also No Property on the image changes here. The content which in this case is `SoftwareBitmap` or `RenderTargetBitmap` changes. The path still remains the same. So `InvokePropertyChanged` will never fire in either cases. – AVK Aug 30 '18 at 13:49
  • 1
    If there a `n` images off course a list is better. No question about it. But in this particular use case, where only four images are used with hardcoded paths, I think its ok to have four properties. I also am aware, that the paths are the same. This is why I suggest to fire the events manually. – ChristianMurschall Aug 30 '18 at 14:08
  • If an `ObservableCollection` is used for the BitmapImages and Bind it to the GridView, how do I update the GridView UI knowing that the BitmapImages Path remain the same and the only thing changing are the Images themselves? – Asem Khen Aug 30 '18 at 14:24
  • @AsemKhen Try `InvokePropertyChanged(nameof(YourObservableCollectionPropertyName));` This might also help: https://stackoverflow.com/questions/5676202/how-to-force-a-wpf-binding-to-refresh – ChristianMurschall Aug 30 '18 at 14:25
  • Your viewmodel needs to implement the `INotifyPropertyChanged` interface. – ChristianMurschall Aug 30 '18 at 14:49
  • @linuxrocks I think this is not supported in UWP apps – Asem Khen Aug 30 '18 at 15:07
  • `INotifyPropertyChanged` is supported in UWP. Add your project to Github If possible. – AVK Aug 30 '18 at 15:27
  • I have also tried creating an observable collection with the images in question. Binded the GridView to this collection, and at each color update I would include this: `GridView.ItemsSource = null;` `GridView.ItemsSource = ImagesCollection;` It would work by changing some Images but not others. this happens randomly. If there it a way to await the first before executing the second, this might work out! – Asem Khen Aug 30 '18 at 15:54
  • But non of the properties has changed. Its only the images changing colors – Asem Khen Aug 31 '18 at 07:01
0

Well I found an indirect dirty way to do it. to update the images in the GridView. I started with clearing the ObservableCollection that the GridView binded to:

ThumnailsCollection.Clear();

Navigate to the folder where the thumbnails are saved to. each type of thumbnails are grouped in one folder. each time the color is changed where the thumbnails for it does not exist, new ones are generated. otherwise, it recalls the ones already on hand:

StorageFolder localFolder =
    Windows.Storage.ApplicationData.Current.LocalFolder;

//Check if the main folder where the images are saved exist 

IStorageItem storageItem = await localFolder.TryGetItemAsync("Thumnails");
if (storageItem != null)
  {
    //If it does, look into the subfolders. each image group of the same
    //type and different colors are saved to tier own folder

    StorageFolder ImagesFolder =
        await localFolder.GetFolderAsync("Thumnails");
    var queryOption =
        new QueryOptions { FolderDepth = FolderDepth.Deep };
    var flatWallpaperSubFolders =
        await ImagesFolder .CreateFolderQueryWithOptions(queryOption).GetFoldersAsync();
    foreach (StorageFolder subFolder in subFolders)
      {
        IStorageItem thumnail =
            await subFolder.TryGetItemAsync($"{AlphaColorID} - {BetaColorID}.png");
        if (thumnail != null)
          {
             //in each of the folders, look if the needed image
             //exist or not
             //If it does, add it to the ObservableCollection
             BitmapImage icon =
                 new BitmapImage(new Uri(subFolder.Path + $"/{AlphaColorID} - {BetaColorID}.png"));
             ThumnailsCollection.Add(new ThumnailsBitmap(icon));
          }
        else
          {
            //If the Image with the requested colors does not exist
            //Render a new image with the needed colors
            //the rendered image is added to the same subfolder with the other
            // similar images
            await ApplyColor(new Uri($"ms-appx:///Images/{subFolder.Name}-Thumnail.png"), $"{AlphaColor} - {BetaColor}.png", $"{subFolder.Name}");
            BitmapImage icon =
                new BitmapImage(new Uri(flatWallpaperSubFolder.Path + $"/{AlphaColor} - {BetaColor}.png"));

            ThumnailsCollection.Add(new ThumnailsBitmap(icon));
          }
      }
  }
else
  {
    //when run for the first time, all folders and images are missing
    //through ApplyColor task, all Images are rendered and folders created
    await ApplyColor(new Uri("ms-appx:///Images/Number-1-Thumnail.png"), $"{AlphaColor} - {BetaColor}.png", "Number-1");

    await ApplyColor(new Uri("ms-appx:///ModernWallpaperGrayscale/Number-2-Thumnail.png"), $"{AlphaColor} - {BetaColor}.png", "Number-2");


    //All needed to do is to all of those Images to the
    //ObservableCollection
    StorageFolder ImagesFolder = await localFolder.GetFolderAsync("Thumnails");
    var queryOption =
        new QueryOptions { FolderDepth = FolderDepth.Deep };
    var flatWallpaperSubFolders =
        await ImagesFolder.CreateFolderQueryWithOptions(queryOption).GetFoldersAsync();
    foreach (StorageFolder subFolder in subFolders)
      {
        BitmapImage icon =
            new BitmapImage(new Uri(subFolder.Path + $"/{AlphaColor} - {BetaColor}.png"));
        ThumnailsCollection.Add(new ThumnailsBitmap(icon));
      }
  }
Asem Khen
  • 317
  • 3
  • 15