this question is a follow up from this one. silverlight 4 image preview from tooltip on datagrid
This is my new problem, I have been trying to get a tool tip to pop up with the preview of the document that is returned in search results of my silverlight app. I have linked the image and it comes up with the correct image, however it opens in a new or separate window instead of the tooltip itself. Here is my code behind..
private void PPTImageToolTip(object sender, RoutedEventArgs e)
{
string docname = ((FrameworkElement)sender).DataContext.ToString();
string baseUri = "http://localhost:58904/ShowDocument.aspx?DocumentName=" + docname + "-ppt" + "&type=jpg";
var hostingWindow = HtmlPage.Window;
hostingWindow.Navigate(new Uri(baseUri, UriKind.Absolute), "_parent");
}
This is set to go to my ShowDocument.aspx page which handles this operation..
else if (File.Exists(strFullFilePath) && sType == "jpg")
{
fileStream = new FileStream(strFullFilePath, FileMode.Open, FileAccess.Read);
buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, Convert.ToInt32(fileStream.Length));
try
{
Response.ClearHeaders();
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.BinaryWrite(buffer);
}
catch (Exception ex)
{ }
}
I realize that it transfers to another 'page' but I have not been able to get that image or that page to show up in the tool tip itself instead of populating the new window. Is this because of my HtmlPage.window code? Or because the ShowDocument.aspx page is already called and it cant call back? Is there a workable solution to get the image to populate inside the tool tip? Or is there a way to repsonse.redirect into the silverlight control that holds the tooltip?
If your aim is to display the image inside the tooltip (and not in the html window), the following will work:
First the web service (ashx)
public class MyHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
String fileName = #"c:\PathToMyFile\Myfile.jpg";
using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
var buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, Convert.ToInt32(fileStream.Length));
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(buffer);
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Then to call the service from the Silverlight client:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
WebClient client = new WebClient();
client.OpenReadCompleted += (s, e) =>
{
using (Stream stream = e.Result)
{
BitmapImage img = new BitmapImage();
img.SetSource(stream);
// Update MyImage.Source. Use the Dispatcher to ensure this happens on the UI Thread
Dispatcher.BeginInvoke(() =>
{
MyImage.Source = img;
});
}
};
client.OpenReadAsync(new Uri(String.Format(BaseURL + "MyHandler.ashx")));
}
}
And finally the xaml for the view:
<Border x:Name="MyBorder" Width="100" Height="100" Background="Black">
<ToolTipService.ToolTip>
<Image x:Name="MyImage" />
</ToolTipService.ToolTip>
</Border>
Related
I am working on an asp.net C# webforms project. I have to debug an issue where once in a while I get "A generic error occurred in GDI+" error. This may be due to too many people accessing the site at the same time. In order to mimic it, I want to create a for loop to create thousands of images and display it through the placeholder. The problem is that, the loop runs and only the last image shows up. I would like to see each and every image created in the loop to be displayed on the page. The following is the code:
protected void btnGenerateBarCode_Click(object sender, System.EventArgs e)
{
System.Web.UI.WebControls.Image imgBarCode = new System.Web.UI.WebControls.Image();
var codabar = new ZXing.BarcodeWriter();
codabar.Options = options;
codabar.Format = ZXing.BarcodeFormat.CODE_128;
for (int i = 1000; i < 2000; i++)
{
using (Bitmap bitMap = new Bitmap(codabar.Write(i.ToString())))
{
using (MemoryStream ms = new MemoryStream())
{
bitMap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] byteImage = ms.ToArray();
Convert.ToBase64String(byteImage);
imgBarCode.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(byteImage);
}
//the placeholder control on the page
plBarCode.Controls.Add(imgBarCode);
}
}
}
The problem is that, the loop runs and only the last image shows up.
This is because you actually create only one control outside of your loop. Add the image creation inside the loop as:
protected void btnGenerateBarCode_Click(object sender, System.EventArgs e)
{
var codabar = new ZXing.BarcodeWriter();
codabar.Options = options;
codabar.Format = ZXing.BarcodeFormat.CODE_128;
for (int i = 1000; i < 2000; i++)
{
using (Bitmap bitMap = new Bitmap(codabar.Write(i.ToString())))
{
// Here create the image control
System.Web.UI.WebControls.Image imgBarCode = new System.Web.UI.WebControls.Image();
using (MemoryStream ms = new MemoryStream())
{
bitMap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] byteImage = ms.ToArray();
Convert.ToBase64String(byteImage);
imgBarCode.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(byteImage);
}
//the placeholder control on the page
plBarCode.Controls.Add(imgBarCode);
}
}
}
I have a simple Window with button and second Window is opened when I click on the Button. Second Window has a Image control, which displays a .png-file. So if I use FileObject property for Binding all is OK, I can delete file from File Explorer. But if I use FileName property for Binding I cannot delete file from File Explorer, I get OS exception. I cannot do this even if I close second window, even if I invoke GC explicitly.
What is the problem with FileName property? Any ideas?
Win 7, Net 4.0
Window1
<Grid>
<Button Content="Ok"
Width="100"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Click="Click"
Padding="0,2,0,2"
IsDefault="True"
Name="_btnOk"/>
</Grid>
public partial class Window : Window
{
public Window()
{
InitializeComponent();
DataContext = this;
}
private void Click(Object sender, RoutedEventArgs e)
{
var window = new Window3();
window.ShowDialog();
}
}
Window2
<Grid>
<Image Source="{Binding FileObject}"></Image>
</Grid>
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
DataContext = this;
FileName = "D:/pdf/myfile.png";
Closing += Window2_Closing;
}
public String FileName { get; set; }
public Object FileObject
{
get
{
if (String.IsNullOrEmpty(FileName))
return null;
if (!File.Exists(FileName))
return null;
var ms = new MemoryStream();
var bi = new BitmapImage();
using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read))
{
fs.CopyTo(ms);
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
}
return bi;
}
}
void Window2_Closing(Object sender, System.ComponentModel.CancelEventArgs e)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
When you bind the Image.Source property to an Uri (or a string, from which an Uri is created internally), WPF uses a built-in type converter that creates a BitmapFrame from the Uri.
If the Uri contains a path to a local file, the BitmapFrame keeps the file open, as long as it is existing. This may be longer than it is actually used in your application, because it may by cached by WPF.
When you need to be able to delete the file that an image was loaded from, you should always use your FileObject approach, but it should look like this:
public ImageSource Image
{
get
{
...
var bi = new BitmapImage();
using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read))
{
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = fs;
bi.EndInit();
}
return bi;
}
}
Or like this:
public ImageSource Image
{
get
{
using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read))
{
return BitmapFrame.Create(
fs, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}
}
Or you bind to the FileName property with a binding converter that creates a BitmapImage or BitmapFrame as shown above.
use this code, I will explain later what is the problem.
var image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image.UriSource = new Uri(FilePath);
image.EndInit();
return image;
You can solve this problem directly from xaml.
<Image>
<Image.Source>
<BitmapImage
CacheOption="OnLoad"
UriSource="{Binding FileName}" />
</Image.Source>
</Image>
I am building my first app in windows phone 7 application. I have an image which comes from the web and when the image is clicked i am navigated to another page.
My xaml code is:
<Button Click="Image_Click" Name="image1" Margin="-33,-16,-26,-13">
<Button.Background>
<ImageBrush Stretch="Fill" ImageSource = "http://political-leader.vzons.com/ArvindKejriwal/images/icons/landing.png"/>
</Button.Background>
</Button>
My .cs code is
private void Image_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/AAP.xaml", UriKind.Relative));
}
Now the issue is that i want to store the image so that it can be even viewed while offline. Can anyone help me what modification should i do to for this purpose.
This is a working example on how to do that. The logic is as follow :
In the page's constructor, call LoadImage method.
The method will set imageBrush's ImageSource to image in Isolated storage if available.
If the image not exists in Isolated storage, LoadImage method will download the image from web and call an event handler when download completed.
The event handler (DownloadCompleted method) will then, save the image to Isolated Storage and call LoadImage again. Refer to point 2 for what happen next.
You may want to improve it later to implement MVVM and using DataBinding.
References: nickharris.net, geekchamp.com
string imageName = "myImage.jpg";
string imageUrl = "http://political-leader.vzons.com/ArvindKejriwal/images/icons/landing.png";
public MainPage()
{
InitializeComponent();
LoadImage();
}
private void LoadImage()
{
BitmapImage bi = new BitmapImage();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
//load image from Isolated Storage if it already exist
if (myIsolatedStorage.FileExists(imageName))
{
using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(imageName, FileMode.Open, FileAccess.Read))
{
bi.SetSource(fileStream);
imageBrushName.ImageSource = bi;
}
}
//else download image to Isolated Storage
else
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(DownloadCompleted);
wc.OpenReadAsync(new Uri(imageUrl, UriKind.Absolute), wc);
}
}
}
private void DownloadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null && !e.Cancelled)
{
try
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(imageName);
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(e.Result);
WriteableBitmap wb = new WriteableBitmap(bitmap);
// Encode WriteableBitmap object to a JPEG stream.
Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
fileStream.Close();
}
//after image saved to Iso storage, call LoadImage method again
//so the method will set imageBrush's ImageSource to image in Iso storage
LoadImage();
}
catch (Exception ex)
{
//Exception handle appropriately for your app
}
}
else
{
//Either cancelled or error handle appropriately for your app
}
}
Hi I am developing a lockscreen app where I am using listbox of images.After selecting a image when i am clicking a button to set lockscreen,It should updated.But it bot updating .Here is my code
private async void ApplicationBarIconButton_Click(object sender, EventArgs e)
{
MediaLibrary mediaLibrary = new MediaLibrary();
//ImageSource im = image1.Source;
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(mediaLibrary.Pictures[imageList.SelectedIndex].GetImage());
String tempJPEG = "MyWallpaper1.jpg";
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(tempJPEG))
{
myIsolatedStorage.DeleteFile(tempJPEG);
}
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(tempJPEG);
StreamResourceInfo sri = null;
Uri uri = new Uri(tempJPEG, UriKind.Relative);
sri = Application.GetResourceStream(uri);
WriteableBitmap wb = new WriteableBitmap(bitmap);
Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 90);
fileStream.Close();
}
LockScreenChange(tempJPEG);
}
private async void LockScreenChange(string filePathOfTheImage)
{
if (!LockScreenManager.IsProvidedByCurrentApplication)
{
await LockScreenManager.RequestAccessAsync();
}
if (LockScreenManager.IsProvidedByCurrentApplication)
{
var schema = "ms-appdata:///Local/";
var uri = new Uri(schema + filePathOfTheImage, UriKind.Absolute);
LockScreen.SetImageUri(uri);
var currentImage = LockScreen.GetImageUri();
MessageBox.Show("Success", "LockScreen changed", MessageBoxButton.OK);
}
else
{
MessageBox.Show("Background cant be changed. Please check your permissions to this application.");
}
}
Actually when first time the app is launched and when I am clicking set button,the current selected image is set as lockscreen,after that when i am selecting another image,it is showing lockscreen changed ,success.No error and no exception.I dont know where is the problem.
Please help........
It got solved by changing temporary file name to original file name i.e. string tempJpeg
When my page loads and I press button1 I can get the image and can see it.
But when I click it second time it doesn't work at all. I debugged it button1_Click(...) and I am sure that imageData != null.
I really can't figure out what's up... Please help me!
private void button1_Click(object button, RoutedEventArgs e)
{
Guid sid = Guid.Parse("087462df-e4b6-484c-879e-cccc37b4c1f4");
EntityQuery<Screenshot> screen = this._myDomainContext.GetScreenshotQuery(sid);
this._myDomainContext.Load(screen).Completed += (sender, args) =>
{
try
{
byte[] imageData = (((LoadOperation<Screenshot>)sender).Entities.FirstOrDefault()).Screen;
if (imageData != null)
{
BitmapImage img = Utilities.Graphics.GetImage(imageData);
img.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image1.Source = null;
image1.Source = img;
}
}
catch
{
}
};
}
and
public static BitmapImage GetImage(byte[] rawImageBytes)
{
BitmapImage imageSource = null;
try
{
using (MemoryStream stream = new MemoryStream(rawImageBytes))
{
stream.Seek(0, SeekOrigin.Begin);
BitmapImage b = new BitmapImage();
b.SetSource(stream);
imageSource = b;
}
}
catch
{
}
return imageSource;
}
Try changing the overload of Load:
this._myDomainContext.Load(screen, LoadBehavior.RefreshCurrent, true).Completed+= ...
I'm not completely sure on the cause if your issue, but I have a few pointers on the code with regards to using BitmapImage's.
There is no need to set the image1.Source property to null before assigning it with an actual source.
Don't dispose the stream you pass to the BitmapImage in case the control is trying to read from it.
I personally make use of BeginInit(...), StreamSource and EndInit(...) when working with BitmapImage's.