Search code examples
c#mvvmwindows-phone-8navigationcimbalino

Call two Interface methods successively in WP8


If I have a Interface like this:

public interface IImageService
{
    ObservableCollection<PictureModel> RefreshSavedImages();

    void PhotoChooserWithCameraServiceShow();
}

And his implementation is :

public class ImageService: IImageService
{
    public ObservableCollection<PictureModel> RefreshSavedImages()
    {
        // Refreash images from library
    }

    public WriteableBitmap StreamToWriteableBitmap(Stream imageStream)
    {
        WriteableBitmap image = new WriteableBitmap(1024, 768);
        image.SetSource(imageStream);
        imageStream.Dispose();
        return image;
    }

    public void PhotoChooserWithCameraServiceShow()
    {
        // PhotoChooserTask get source of image.
    }
}

When I have the implementation in a ViewModel:

private readonly IImageService imageService;
public MainViewModel(IImageService imageService)
    {
        this.imageService = imageService;
    }
private void MethodA()
    {
        // Choose Photo, I edited it and after saved it.
        imageService.PhotoChooserWithCameraServiceShow();
        // Refreash the library and Bind it in my ItemSource from my ListBox.
        PictureList = imageService.RefreshSavedImages();
    }

My problem is that I need first finish this method: imageService.PhotoChooserWithCameraServiceShow(); and after continue with imageService.RefreshSavedImages();

The problem is that what my program do is execute the second before the first is completed.

Problems that I think can cause this issue:

  1. From a ViewModel call NavigationService without logic to goback. So the can't:

    NavigationService navigation = new NavigationService(); navigation.NavigateTo(new Uri("/Views/SecondPage.xaml", UriKind.Relative));

The PhotoChooserWithCameraServiceShow is taken from the Cimbalino Windows Phone Toolkit

Thanks for all and greetings!


Solution

  • You need to set up an event listener for the photo chooser task's completed event and call imageService.RefreshSavedImages(); from there.

    If you update your interface, you can add an event handler to your PhotoChooserWithCameraServiceShow method:

    public interface IImageService
    {
        ObservableCollection<object> RefreshSavedImages();
        void PhotoChooserWithCameraServiceShow(EventHandler<PhotoResult> CompletedCallback);
    }
    

    Then in your interface implementation, assign that callback to the PhotoChooserTask Completed event. I'm assuming you're declaring your PhotoChooserTask in this class:

    public class ImageService: IImageService
    {
        PhotoChooserTask photoChooserTask;
        public ImageService()
        {
            photoChooserTask = new PhotoChooserTask();
        }        
    
        public ObservableCollection<PictureModel> RefreshSavedImages()
        {
            // Refreash images from library
        }
    
        public WriteableBitmap StreamToWriteableBitmap(Stream imageStream)
        {
           ....
        }
    
        public void PhotoChooserWithCameraServiceShowEventHandler<PhotoResult> CompletedCallback)
        {
            // PhotoChooserTask get source of image.
            photoChooserTask.Completed += CompletedCallback;        
        }
    }
    

    Finally, in your view model you can implement the actual callback:

    private void MethodA()
    {
        // Choose Photo, I edited it and after saved it.
        imageService.PhotoChooserWithCameraServiceShow(photoChooserTask_Completed);
    }
    
    // this is your callback
    void photoChooserTask_Completed(object sender, PhotoResult e)
        {
            if (e.TaskResult == TaskResult.OK)
            {
                // Refreash the library and Bind it in my ItemSource from my ListBox.
                PictureList = imageService.RefreshSavedImages();
            }
        }
    

    See the details and examples here.