System.Drawing alternative in wpf? - c#

Hi I am running into a small problem with loading a Bitmap image from a wcf rest service:
public Image GetImage(int width, int height)
{
string uri = string.Format("http://localhost:8000/Service/picture/{0}/{1}", width, height);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
return new Bitmap(stream); //no System.Drawing.Bitmap class in wpf?
}
}
}
Seems there is no System.Drawing class for wpf so how can I fix this? Another problem related to this is how do I set the source:
image1.Source = GetImage(image1.Height, image1.Width); //best overload for this line
// also not sure if source would be correct?
In windows forms you can do this:
pictureBox1.Image = GetImage(pictureBox1.Height, pictureBox1.Width);
Which works fine but wpf obviously has to annoy me to no end!
Im really hoping there is something simple that can be done here?
<GroupBox Height="141" HorizontalAlignment="Left" Name="groupBox1" VerticalAlignment="Top" Width="141" BorderBrush="#FFA3A3A3" Background="#37000000" Margin="1,21,0,0">
<Image Name="image1" Stretch="Fill"/>
</GroupBox>

WPF shouldn't annoy you. It's even easier.
<GroupBox Height={Binding Height}" Width="{Binding Width"}>
<Image Source="{Binding MyImageUrl}" />
</GroupBox>
Your view model could be something like
public class ImageViewModel : INotifyPropertyChanged
{
public string ImageUrl
{
get
{
return "your url here";
}
}
public double Width
{
get { return "required width"; }
}
public double Height
{
get { return "required height"; }
}
}
and of course you would need to implement INotifyPropertyChanged.

Related

how to display an image on xamarin forms using binding tag from image

Using xamarin forms trying to display an image using binding...followed a few online Q's already including the answer on this one https://stackoverflow.com/questions/30850510/how-to-correctly-use-the-image-source-property-with-xamarin-forms just cant seem to get the image to display...yes I knoW I can load the image by using <Image Source="Bud.jpeg"></Image> which works fine....but I would like to display it using binding....
eg..
xaml
<Image Source="{Binding imageTest}"></Image>
code
var imageTest = new Image { Aspect = Aspect.AspectFit };
imageTest.Source = ImageSource.FromFile("Guinness.jpg");
anyone any idea why? thanks
You can only bind to public properties
<Image Source="{Binding imageTest}" />
then declare a public property in your code-behind
public string imageTest { get; set; }
and then set the property value and BindingContext
imageTest = "Guinness.jpg";
this.BindingContext = this;

WPF XAML serialize/deserialize

my application is basically taking one WPF Canvas containing other controls and serialize it to an XML file and then deserialize it to display the serialized data or a previously saved one. The serialization/deserialization is working fine everything is saved and restored back. The issue is that after deserialization if I try to change an image source with the bellow code it doesn't work:
testLogo.Source = new BitmapImage(new Uri(file.FileName));
The Image is referrenced in the XAML as bellow:
<Canvas Name="mainCanva" Margin="0,0,12,0" Width="1729" Height="150" VerticalAlignment="Top">
<Border BorderThickness="3" BorderBrush="#FF009B80" FlowDirection="LeftToRight" VerticalAlignment="Top" HorizontalAlignment="Left" Width="1729" Height="150">
<Grid Margin="0" Background="White" Height="Auto" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Uid="">
<Grid HorizontalAlignment="Left" Margin="3,28,0,57">
<Image HorizontalAlignment="Left" Margin="0,0,0,0" x:Name="testLogo" Stretch="UniformToFill" Width="317" Source="file:///C:/Users/logo.jpg" />
</Grid>
</Grid>
</Border>
</Canvas>
The Deserialization code is as bellow:
Canvas canvas = DeSerializeXAML(appPath + "\\tmp\\mainCanva.xml") as Canvas;
mainCanva.Children.Clear();
while (canvas.Children.Count > 0)
{
UIElement obj = canvas.Children[0];
canvas.Children.Remove(obj);
mainCanva.Children.Add(obj); // Add to canvas
}
Another point to note is that I tried to find out what was happening using Snoop, after Deserialization Snoop is also unable to change the image source although if I reconnect Snoop to the app by drag and dropping the crosshair Snoop is now able to change the Image source. The 'old' Snoop window can see the image source being updated from the testLogo.Source = command. WPF inspector doesn't have this issue it is immediately updating itself when the deserialization is happening. My guess is that there is something wrong with the visual tree ... and as WPF can do it I think it can be sorted.
Thanks for the help guys.
As requested the Serialize/Deserialize functions:
public static void SerializeToXAML(UIElement element, string filename)
{
string strXAML = System.Windows.Markup.XamlWriter.Save(element);
using (System.IO.FileStream fs = System.IO.File.Create(filename))
{
using (System.IO.StreamWriter streamwriter = new System.IO.StreamWriter(fs))
{
streamwriter.Write(strXAML);
}
}
}
public static UIElement DeSerializeXAML(string filename)
{
using (System.IO.FileStream fs = System.IO.File.Open(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
return System.Windows.Markup.XamlReader.Load(fs) as UIElement;
}
}
You need to update your variable reference.
When you call mainCanva.Children.Clear(), it removes all the children including testLogo. Your variable testLogo will still be pointing at the original testLogo object even though it's not part of the UI anymore.
Try this:
Canvas canvas = DeSerializeXAML(appPath + "\\tmp\\mainCanva.xml") as Canvas;
mainCanva.Children.Clear();
while (canvas.Children.Count > 0)
{
UIElement obj = canvas.Children[0];
canvas.Children.Remove(obj);
mainCanva.Children.Add(obj); // Add to canvas
}
testLogo = mainCanva.FindName("testLogo") as Image;
I ended up using Application resources:
<Application.Resources>
<BitmapImage x:Key="testLogo" >file:///C:/Users/test_B&W.png</BitmapImage>
</Application.Resources>
then in the code:
Resources["AVItestLogoic"] = ...
This way no matter what happens to the Visual Tree, the application resource always point to the right item

XAML, Image control, local storage image

The first is the first, I'm very newbie on .NET, I was developed un Visual Basic 6, but now I'm trying to make an application to Windows Phone 8.0.
At this time I'm trapped with a (maybe simple) problem.
I have a xaml page with control, and it is part of LongListSelector thats implements an Observable Collection of "Prenda" class.
...
var prendasData = from r in db.Prendas select r;
PrendasItems = new ObservableCollection<Prenda>(prendasData);
llsPrendas.ItemsSource = PrendasItems;
...
The XAML portion is the code bellow, please, i know that severals things maybe are wrong, but I'm learning alone, be patient with me :D
<phone:LongListSelector x:Name="llsPrendas" Margin="0,0,-12,0" ItemsSource="{Binding Prendas}" SelectionChanged="llsPrendasSelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Width="100" Height="100" Margin="5,0,0,0" Source="{Binding PrendaImageURI}" ImageFailed="errcargaimg"/>
<StackPanel Orientation="Vertical">
<TextBlock FontWeight="Normal" Text="{Binding Nombre}" Margin="10,0,0,0" />
<TextBlock FontWeight="Normal" Text="{Binding Precio}" Margin="10,0,0,0" />
</StackPanel>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
The problem is the Image Control. It doesn't show anything and if I debug it, the error the message is: "AG_E_NETWORK_ERROR", googled this error and I know that is (in this case) same as "File not found." But I'm sure thats file exists. because I seen it with IsoStoreSpy, at /Shared/Media/ShellContent/WP_XXX.jpg, i think that the root of the Isolated Storage is called isostore:/ and the complete URI must be: isostore:/Shared/Media/ShellContent/WP_XXX.jpg.
This string is saved as string column in the class, and I create a property thats use this string to make an Uri to use to bind the Source property of Image control at design time.
(portion of class declaration)
[Column]
public string Foto
{
get
{
return foto;
}
set
{
if (foto != value)
{
foto = value;
NotifyPropertyChanged("Foto");
}
}
}
public Uri PrendaImageURI
{
get
{
return new Uri(this.Foto, UriKind.Absolute);
}
}
I'm going crazy, because I cannot understand why it's doesn't work. Can somebody help me? (Sorry for my bad english)
You can not read from Isolated storage using URI, You have to read using IsolatedStorageFile class:
private static BitmapImage GetImageFromIsolatedStorage(string imageName)
{
var bimg = new BitmapImage();
using (var iso = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var stream = iso.OpenFile(imageName, FileMode.Open, FileAccess.Read))
{
bimg.SetSource(stream);
}
}
return bimg;
}
You can find more details from below Posts:
How get image from isolated storage
How to load an image from isolated storage into image control on windows phone?
I solved it with Pratik Goyal help (thank you, very much!), making a BitmapImage Property in the class "Prendas", taking The Foto string data. Later I will take more careful with the exception control, but is a good start, I think.
public BitmapImage ImageFoto
{
get
{
return GetImageFromIsolatedStorage(Foto);
}
}
public BitmapImage GetImageFromIsolatedStorage(string imageName)
{
var bimg = new BitmapImage();
using (var iso = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var stream = iso.OpenFile(imageName, FileMode.Open, FileAccess.Read))
{
bimg.SetSource(stream);
}
}
return bimg;
}
Just for the children:
Silverlight notifies this with an AG_E_NETWORK_ERROR / HRESULT=0x80131500. Which of course can't be found anywhere on the web and of course means jack and shit to me and not only to me.
Is the UI being notified of the PrendaImageURI property changing?
Try adding
NotifyPropertyChanged("PrendaImageURI");
when your Foto property is set.

Binding image to property in wpf with image from resources

i have some pictures included to my project.
this line of code works fine:
<Image Stretch="UniformToFill" Source="/Images/OffsetSituations/offsetsituation1.jpg"
but i have to change the picture from the VM so i made a property to bind to:
private ImageSource _image;
public ImageSource Image
{
get { return _image; }
set
{
if (_image == value)
return;
_image = value;
RaisePropertyChanged("Image");
}
}
from another post here on stackoverflow i got this code and changed it a bit:
string picture = "offsetsituation1";
if (!string.IsNullOrEmpty(picture))
{
var image = new BitmapImage(new Uri(String.Format("/Images/OffsetSituations/{0}.jpg", picture), UriKind.Relative));
image.Freeze(); // -> to prevent error: "Must create DependencySource on same Thread as the DependencyObject"
Image = image;
}
else
{
Image = null;
}
now in the xaml:
<Image Stretch="UniformToFill" Source="{Binding Image}" Margin="5"/>
but there never is a picture.
i added MessageBox.Show(Image.ToString()); after Image = image; to debug. it shows /Images/OffsetSituations/offsetsituation1.jpg, so the path seems to be right.
what am i doing wrong here?
WPF provide implicit converters for most of the framework types including ImageSource
all you have to do is provide the correct image path as string and let the implicit converter do the rest
so change the type of Image property to string
eg
public string Image
{
get { return _image; }
set
{
if (_image == value)
return;
_image = value;
RaisePropertyChanged("Image");
}
}
and assign the path as a string
Image = String.Format("/Images/OffsetSituations/{0}.jpg", picture);
that's all you need to show the image, rest will be handled by the framework
implicit converter are so handy in many places including this one.

Image from isolated storage

I am trying to bind an image that is saved in isolated storage and display it on the same screen as the camera, but I can't seem to get the image to display. I don't know if it because I am not saving it on the phones camera roll, but I am not saving them because I am gonna take multiple pictures and display them like a film strip across the bottom of the view finder for the camera. Can anyone help me please?
I am using this tutorial Here
public partial class Page1 : PhoneApplicationPage
{
private static ObservableCollection<PhotoImage> photoList = new ObservableCollection<PhotoImage>();//For the class and list
private int savedCounter = 0;
public Page1()
{
InitializeComponent();
}
private void ShutterButton_Click(object sender, RoutedEventArgs e)
{
if (cam != null)
{
try
{
// Start image capture.
cam.CaptureImage();
}
catch (Exception ex)
{
this.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = ex.Message;
});
}
}
}
void cam_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e)
{
// Increments the savedCounter variable used for generating JPEG file names.
savedCounter++;
}
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
string fileName = "MyImage" + savedCounter + ".jpg";
try
{
// Save picture to the library camera roll.
//library.SavePictureToCameraRoll(fileName, e.ImageStream);//dont want to save it to the camera roll
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
// Save picture as JPEG to isolated storage.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to isolated storage.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
photoList.Add(new PhotoImage(fileName));//here is where I set with the file name
listBoxSearch.ItemsSource = photoList; //here is the binding
});
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
public class PhotoImage
{
public string PhotoItem { get; set; }
public PhotoImage(string pItem)
{
this.PhotoItem = pItem;
}
}
here is my XAML code
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="640" />
<ColumnDefinition Width="160" />
</Grid.ColumnDefinitions>
<Canvas x:Name="viewfinderCanvas" Width="640" HorizontalAlignment="Left" Margin="0,0,0,143">
<!--Camera viewfinder -->
<Canvas.Background>
<VideoBrush x:Name="viewfinderBrush" />
</Canvas.Background>
<TextBlock Height="40" Name="txtDebug" Width="626" FontSize="24" FontWeight="ExtraBold" Canvas.Left="14" Canvas.Top="297" />
</Canvas>
<!--Button StackPanel to the right of viewfinder>-->
<StackPanel Grid.Column="1" >
<Button x:Name="ShutterButton" Content="SH" Click="ShutterButton_Click" FontSize="26" FontWeight="ExtraBold" Height="75" />
</StackPanel>
<Grid>
<ListBox Foreground="RoyalBlue" Height="131" Name="listBoxSearch" Width="438" TabIndex="10" Margin="96,343,106,6">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="Auto" >
<Image Height="73" Width="73" VerticalAlignment="Top" Margin="0,10,8,0" Source="{Binding PhotoItem }" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
Okay - the issue is that does not have an implicit converter that knows how to take an IsoStorage URI and load it.
One easy solution is to add another property to your PhotoImage class and bind to it instead - here's a quick and dirty:
public ImageSource SourceItem
{
get
{
BitmapImage image = new BitmapImage();
image.SetSource(isStore.OpenFile(PhotoItem, FileMode.Open));
return image;
}
}
Note that this is not a great solution - I am just showing you the general idea. Things to think about when implementing your own:
The stream is not being discarded. Wrap the Stream in a using when setting it into image.
Depending on what you are trying to do, you may want to use image.CreateOptions to make the app more responsive (but then you need to figure out how to handle the stream needing to be kept opened)
Finally, the image that will be loaded will be at full resolution. You may want to look into PictureDecoder.DecodeJpeg() to load a thumbnail of the image instead (or look at the thumbnail provided by the camera object)

Categories