void XamlBuilder::SetImageOnUIElement()

in source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp [275:424]


    void XamlBuilder::SetImageOnUIElement(winrt::Uri const& imageUrl,
                                          T const& uiElement,
                                          winrt::AdaptiveCardResourceResolvers const& resolvers,
                                          bool isAutoSize,
                                          winrt::IInspectable const& parentElement,
                                          winrt::IInspectable const& imageContainer,
                                          bool isVisible,
                                          winrt::Stretch stretch)
    {
        bool mustHideElement = true;

        // Get the image url scheme
        winrt::hstring schemeName = imageUrl.SchemeName();

        // Get the resolver for the image
        if (resolvers)
        {
            auto resolver = resolvers.Get(schemeName);
            // If we have a resolver
            if (resolver)
            {
                // Create a BitmapImage to hold the image data.  We use BitmapImage in order to allow
                // the tracker to subscribe to the ImageLoaded/Failed events
                winrt::BitmapImage bitmapImage{};

                if (!m_enableXamlImageHandling && (m_listeners.size() != 0))
                {
                    this->m_imageLoadTracker->TrackBitmapImage(bitmapImage);
                }

                bitmapImage.CreateOptions(winrt::BitmapCreateOptions::None);

                // Create the arguments to pass to the resolver
                auto args = winrt::make<winrt::implementation::AdaptiveCardGetResourceStreamArgs>(imageUrl);

                // And call the resolver to get the image stream
                auto getResourceStreamOperation = resolver.GetResourceStreamAsync(args);

                getResourceStreamOperation.Completed(
                    [this, weakThis = this->get_weak(), uiElement, bitmapImage, stretch, isAutoSize, parentElement, imageContainer, isVisible](
                        winrt::IAsyncOperation<winrt::IRandomAccessStream> const& operation, winrt::AsyncStatus status) -> void
                    {
                        if (status == winrt::AsyncStatus::Completed)
                        {
                            if (auto strongThis = weakThis.get())
                            {
                                auto randomAccessStream = operation.GetResults();
                                if (!randomAccessStream)
                                {
                                    this->m_imageLoadTracker->MarkFailedLoadBitmapImage(bitmapImage);
                                    return;
                                }
                                SetImageSource(uiElement, bitmapImage, stretch);

                                auto setSourceAction = bitmapImage.SetSourceAsync(randomAccessStream);

                                setSourceAction.Completed(
                                    [weakThis, uiElement, isAutoSize, parentElement, imageContainer, isVisible](
                                        winrt::IAsyncAction const&, winrt::AsyncStatus status)
                                    {
                                        if (status == winrt::AsyncStatus::Completed && isAutoSize)
                                        {
                                            if (auto strongThis = weakThis.get())
                                            {
                                                strongThis->SetAutoSize(uiElement, parentElement, imageContainer, isVisible, false /* imageFiresOpenEvent */);
                                            }
                                        }
                                    });
                            }
                        }
                        else
                        {
                            if (auto strongThis = weakThis.get())
                            {
                                this->m_imageLoadTracker->MarkFailedLoadBitmapImage(bitmapImage);
                            }
                        }
                    });
            }
        }

        if (schemeName == L"data")
        {
            // Decode base 64 string
            winrt::hstring dataPath = imageUrl.Path();
            std::string data = AdaptiveBase64Util::ExtractDataFromUri(HStringToUTF8(dataPath));
            std::vector<char> decodedData = AdaptiveBase64Util::Decode(data);

            winrt::DataWriter dataWriter{winrt::InMemoryRandomAccessStream{}};

            dataWriter.WriteBytes(std::vector<byte>{decodedData.begin(), decodedData.end()});

            winrt::BitmapImage bitmapImage{};
            bitmapImage.CreateOptions(winrt::BitmapCreateOptions::IgnoreImageCache);
            m_imageLoadTracker->TrackBitmapImage(bitmapImage);

            auto streamWriteOperation = dataWriter.StoreAsync();

            streamWriteOperation.Completed(
                [weakThis = this->get_weak(), dataWriter, bitmapImage, uiElement, isAutoSize, parentElement, imageContainer, isVisible](
                    winrt::IAsyncOperation<uint32_t> const& /*operation*/, winrt::AsyncStatus /*status*/) -> void
                {
                    if (auto strongThis = weakThis.get())
                    {
                        if (const auto stream = dataWriter.DetachStream().try_as<winrt::InMemoryRandomAccessStream>())
                        {
                            stream.Seek(0);
                            strongThis->SetImageSource(uiElement, bitmapImage);
                            auto setSourceAction = bitmapImage.SetSourceAsync(stream);

                            setSourceAction.Completed(
                                [weakThis, bitmapImage, isAutoSize, parentElement, imageContainer, isVisible](
                                    winrt::IAsyncAction const& /*operation*/, winrt::AsyncStatus status)
                                {
                                    if (status == winrt::AsyncStatus::Completed && isAutoSize)
                                    {
                                        if (auto strongThis = weakThis.get())
                                        {
                                            strongThis->SetAutoSize(bitmapImage, parentElement, imageContainer, isVisible, false /* imageFiresOpenEvent */);
                                        }
                                    }
                                });
                        }
                    }
                });
            m_writeAsyncOperations.push_back(streamWriteOperation);
            mustHideElement = false;
            return;
        }

        // Otherwise, no resolver...
        if ((m_enableXamlImageHandling) || (m_listeners.size() == 0))
        {
            // If we've been explicitly told to let Xaml handle the image loading, or there are
            // no listeners waiting on the image load callbacks, use Xaml to load the images
            winrt::BitmapImage bitmapImage{};
            bitmapImage.UriSource(imageUrl);

            SetImageSource(uiElement, bitmapImage, stretch);

            if (isAutoSize)
            {
                SetAutoSize(uiElement, parentElement, imageContainer, isVisible, true /* imageFiresOpenEvent */);
            }
        }
        else
        {
            PopulateImageFromUrlAsync(imageUrl, uiElement);
        }
    }