I want to take a photo with the camera and show it on the page I am at
So I have a ViewModel where I both take the picture and show it
public class CamViewModel : MvxViewModel,
IMvxServiceConsumer<IInstalledMeter>,
IMvxServiceConsumer<ICamaraService>
{
public CamViewModel()
{
this.GetService<ICamaraService>().PhotoSavedEvent += PhotoSaved;
if (!String.IsNullOrEmpty(this.GetService<IInstalledMeter>().ImagePath))
{
ImagePath = this.GetService<IInstalledMeter>().ImagePath;
}
TakePicture();
}
private string _imagePath;
public string ImagePath
{
get { return _imagePath; }
set { _imagePath = value; FirePropertyChanged("ImagePath"); }
}
//Navigate back to InstallUnit
public IMvxCommand OpenCamaraCommand
{
get
{
return new MvxRelayCommand(TakePicture);
}
}
private void PhotoSaved(object sender, PhotoSavedResultEventArgs e)
{
ImagePath = e.ImagePath;
}
private void TakePicture()
{
this.GetService<ICamaraService>().TakePhoto();
}
}
This uses a CameraService that both takes the picture and saves the picture on isolated storage (I know, bad seperation of concern)
public class CamaraService : IMvxServiceConsumer<IMvxPictureChooserTask>, IMvxServiceConsumer<IMvxSimpleFileStoreService>, IMvxServiceConsumer<IInstalledMeter>, ICamaraService
{
private const int MaxPixelDimension = 1024;
private const int DefaultJpegQuality = 70;
public event EventHandler<PhotoSavedResultEventArgs> PhotoSavedEvent;
private void PhotoTaken(PhotoSavedResultEventArgs e)
{
if (PhotoSavedEvent != null)
{
PhotoSavedEvent(this, e);
}
}
public string ImagePath { get; set; }
public void TakePicture()
{
this.GetService<IMvxPictureChooserTask>().TakePicture(
MaxPixelDimension,
DefaultJpegQuality,
SavePicture,
() => { /* cancel is ignored */ });
}
public void TakePhoto()
{
TakePicture();
}
public void SavePicture(Stream image)
{
var newImage = Save(image);
if (newImage != "")
{
DeleteOldImage(this.GetService<IInstalledMeter>().ImagePath);
this.GetService<IInstalledMeter>().ImagePath = newImage;
PhotoTaken(new PhotoSavedResultEventArgs {ImagePath = newImage});
}
}
public void UpdateModel(string filename)
{
}
public void DeleteOldImage(string fileName)
{
try
{
if (String.IsNullOrEmpty(fileName)) return;
var fileService = this.GetService<IMvxSimpleFileStoreService>();
fileService.DeleteFile(fileName);
}
catch
{
}
}
public string Save(Stream stream)
{
try
{
var fileName = Guid.NewGuid().ToString();
var fileService = this.GetService<IMvxSimpleFileStoreService>();
fileName = Path.Combine("Image", fileName);
fileService.WriteFile(fileName, stream.CopyTo);
return fileName;
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
return "";
}
}
}
The View on Windows Phone to display the image is
<Views:BaseCamView
x:Class="UI.WP7.Views.InstallMeter.CamView"
xmlns:Views="clr-namespace:UI.WP7.Views.InstallMeter"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:nativeConverters="clr-namespace:UI.WP7.NativeConverters"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">
<Views:BaseCamView.Resources>
<nativeConverters:PathToImageConverter x:Name="PathToImageConverter" />
</Views:BaseCamView.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY sdf" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="{Binding ImagePath}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Image Grid.Row="1" Source="{Binding ImagePath, Converter={StaticResource PathToImageConverter}}" Height="200" Width="700" Stretch="Uniform" />
</Grid>
And this view uses a converter to convert the path to a bitmapimage
public class PathToImageConverter : IValueConverter, IMvxServiceConsumer<IMvxSimpleFileStoreService>
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
byte[] contents = null;
try
{
var file = this.GetService();
file.TryReadBinaryFile((string)value, out contents);
}
catch (Exception)
{
// masked
}
if (contents == null)
return null;
using (var stream = new MemoryStream(contents))
{
var image = new BitmapImage();
image.SetSource(stream);
return image;
}
}
But when ever I try to take a picture this bit in the converter returns null
if (contents == null)
return null;
So I presume that means the image is not accessable / saved or the filename is wrong, but not sure where the error happens