2

In XAML I have below line in ItemControl DataTemplate. Source pic is bind to Image from c#.But the loading of pic is taking some time.Till thenI want to display some default image and load other UI elements in that xaml file.

<Image Grid.Row="0" Source="{Binding pic}" Stretch="Fill"  />

How to display default image till original pic is loaded from pic URL(url to server) and replace it with loaded image after done with pic loading from url?

Solution by Peter works, But the problem is my app hangs for around 10 seconds just before its displaying the image from server url. Code mentioned below

<ItemsControl x:Name="StoreCards" Margin="20" 
                      HorizontalAlignment="Center" VerticalAlignment="Top"
                      Grid.Row="2" AlternationCount="100000" >
            <ItemsControl.ItemTemplate>
                <DataTemplate>
  <Button BorderBrush="Black" Background="White" BorderThickness="0.2" Margin="10" Click="Card_Click">
                        <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <Rectangle Fill="Red" Stretch="UniformToFill"/>
                            <Image x:Name="BannerImage" Stretch="UniformToFill">
                                <Image.Source>
                                    <BitmapImage UriSource="{Binding pic, IsAsync="True"}"/>
                                </Image.Source>
                            </Image>
                     </Grid>
        </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel ItemHeight="200" ItemWidth="300"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>

Thanks

djkpA
  • 1,224
  • 2
  • 27
  • 57
  • See [this answer](http://stackoverflow.com/a/16036994/1997232), you could presumably use some trigger in xaml to display something else until image is loaded (or with [code-behind](http://stackoverflow.com/q/24087058/1997232)). – Sinatr Mar 20 '17 at 11:12
  • That's a list of Images in DataTemplate. I appended List to ItemSource which contains pic as one key and its value is image link. – djkpA Mar 20 '17 at 11:19
  • You should then bind to a ImageLoader class that would contain DefaultImage property, a Loaded boolean property and the ServerImage property. Using a trigger you can bind the DefaultImage visibility to Loaded property, and then in your viewmodel you just change Loaded property to true, once you load the image from server, and then trigger would hide DefaultImage and show ServerImage. – Ricardo Serra Mar 20 '17 at 11:23
  • Is the image loaded from a URI, or do you create an ImageSource after downloading? In the latter case you may perhaps use a PriorityBinding. – Clemens Mar 20 '17 at 11:30
  • `Source="{Binding pic}"` here I am binding pic to server URI.Its loaded from URI – djkpA Mar 20 '17 at 11:32
  • You could load the image in your `VM`. So you can use the Async Property while binding. I had a simmiliar issue with thumbnails of svg elements, because i have to use a third party framework for it - that took forever. So i loaded the image in Property and set it async as shown in my sample. – Peter Mar 22 '17 at 14:37
  • Could you provide some example.That would be very helpful. – djkpA Mar 22 '17 at 14:39
  • `private BitmapImage pic; public BitmapImage Pic { get { if(pic == null) { pic = new BitmapImage(MyUriSource); } return pic; } }` – Peter Mar 22 '17 at 14:45
  • Will this work for `` inside data template – djkpA Mar 22 '17 at 14:56
  • Updated question with the exact code. – djkpA Mar 22 '17 at 15:00
  • Check out https://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level – Peter Mar 22 '17 at 16:07
  • And the ugly solution ! would be loading the image in the code behind asynchronusly mate ! Check out tutorial. – Peter Mar 22 '17 at 16:09
  • If you just want to fast solution then go for Loaded event:` private void Image_Loaded(object sender, RoutedEventArgs e) { Image self = sender as Image; if(self != null) { Uri uri = (Uri) self.DataContext; self.Source = new BitmapImage(uri); } }` – Peter Mar 22 '17 at 16:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/138759/discussion-between-djkp-and-peter). – djkpA Mar 22 '17 at 18:46
  • Feel free to accept my answer mate – Peter Jul 03 '17 at 15:13

1 Answers1

2

This is not beautiful, but it is the easiest way.

Lets assume your Placeholder-Image is a Rectangle. This is the solution:

<Grid>
    <Rectangle Fill="Red" 
        Width="40"
        Height="40"
        />
    <Image 
        Stretch="Fill"
        Height="40"
        Width="40"
        Source="{Binding Path=pic, IsAsync=True}"
        />
</Grid>

Of course it will have overhead with 2 images, but its so easy this way!

Peter
  • 1,655
  • 22
  • 44
  • Yeah this worked , But the problem is my app hangs for around 10 seconds just before it displays downloaded image – djkpA Mar 22 '17 at 14:27
  • This is a problem of your implementation. You should use the asnyc-await-pattern. I showed this with `Source="{Binding Path=pic, IsAsync=True}"` – Peter Mar 22 '17 at 14:28
  • There is IsAsync=True in your solution right. I used the same – djkpA Mar 22 '17 at 14:29
  • Provide code how you load the image mate ... I would assume you load it sync in the ui-thread. Then of course everything freezes or start is taking so long. ;) – Peter Mar 22 '17 at 14:31