dynamically handling events for an image - c#

I'm currently working on a program where there are multiple "icons" dynamically added to a window. Each one of these "icons" (which is actually a image with a label underneath it) represents a device in a network. When the user double clicks on an icon, it needs to open a window where the user can change the properties of that specific device.
I already have the window created, along with the code to dynamically add images to a window. My problem is that since each icon is dynamically added, they use the same event handler. since each icon uses the same handler, it seems impossible to have each icon open its respective device.
Here is a part of the code which is run when a user adds a new device along with the event handler it uses:
//create new device
devices.Add(new Device(ipaddress, hn, un, pw, cm, lx, ly, tp, pl, nt, dn));
images.Add(new Image());
//create image for main window
images[images.Count - 1].Width = 50;
images[images.Count - 1].Height = 35;
images[images.Count - 1].Stretch = Stretch.Fill;
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri(deviceImages[tp], UriKind.Relative);
logo.CacheOption = BitmapCacheOption.OnLoad;
logo.EndInit();
images[images.Count - 1].Source = logo;
images[images.Count - 1].Cursor = Cursors.Hand;
images[images.Count - 1].Margin = new System.Windows.Thickness(lx-25, ly-25, 0, 0);
images[images.Count - 1].VerticalAlignment = System.Windows.VerticalAlignment.Top;
images[images.Count - 1].HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
images[images.Count - 1].MouseDown += new MouseButtonEventHandler(deviceIcon_MouseDown);
ConnexMainWindow.grid1.Children.Add(images[images.Count - 1]);
public void deviceIcon_MouseDown(object sender, MouseButtonEventArgs e)
{
ConnexDeviceWindow deviceWindow = new ConnexDeviceWindow();
deviceWindow.Show();
}
As you can see, I'm not currently passing the device window the device since there isn't really any way to do so from the event handler.
My question is: Is there a way to dynamically create an event handler, for each image i add, so that i can pass the function the proper device that each image represents?

One common strategy to identify the control which fired the event is to use the Tag property of the control to store some information.
I don't know what your device model looks like, but let's assume the ip-address is unique among all the devices. You can attach that to the Image control:
images[images.Count - 1].Tag = ipaddress
In your event handler you can grab that tag to find the device (assuming the devices collection is available on class-level):
public void deviceIcon_MouseDown(object sender, MouseButtonEventArgs e)
{
Image image = e.Source as Image;
if (image != null)
{
string ipAddress = (string)image.Tag;
Device device = devices.FirstOrDefault(d => d.IpAddress == ipAddress);
if (device != null)
{
ConnexDeviceWindow deviceWindow = new ConnexDeviceWindow(device);
deviceWindow.Show();
}
}
}

Related

I'm lost at how to configure my code so that , when i click the radio button a certain image appears

I have to create a small pizza delivery program in C# using Visual Studio 2019 Community Edition :
It has 3 Radio Buttons ( for 3 different pizza's), A Textblock for text ( to show the ingredients), and an image to show the type of pizza.
So I want that when I click on one of those 3 Radio Buttons, a certain text & image appears.
The Radio Buttons and TextBlock is ok, but the image I'm lost at how to properly configure it using the code behind.
Can anyone check the code, and maybe enlighten me?
https://ideone.com/e.js/MjEBnd
private void radiobtnHawai_Checked(object sender, RoutedEventArgs e)
{
string Hawai = "Ananas, Kip, Kaas";
lbl1.Text = Hawai;
Image Hawai.jpg = new Image();
BitmapImage bi3 = new BitmapImage();
bi3.BeginInit();
bi3.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative);
bi3.EndInit();
Hawai.jpg.Stretch = Stretch.Fill;
Hawai.jpg.Source = bi3;
}
Here is an Extra Image : https://i.stack.imgur.com/iiHRn.png
Thanks in Advance,
If more information is needed, please don't hesitate to ask.
Suppose you have a image control defined like this
<Image Name="ImageViewer1" Height="400" Width="400" />
On your radio checked command , you have to assign the source of "ImageViewer1".
For example, in your case it will look like this
private void radiobtnHawai_Checked(object sender, RoutedEventArgs e)
{
string Hawai = "Ananas, Kip, Kaas";
lbl1.Text = Hawai;
BitmapImage bi3 = new BitmapImage();
bi3.BeginInit();
bi3.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative);
bi3.EndInit();
ImageViewer1.Stretch = Stretch.Fill;
ImageViewer1.Source = bi3;
}
Also make sure that, smiley_stackpanel.PNG, exists in your Environment.CurrentDirectory.
By specifying relative path it will look images from the path where your exe resides

C# add a click event to grid childs

How can I add a click event to child objects I have created in my Code Behind?
String[] imageNames = System.IO.Directory.GetFiles("Assets/Images/Gallery");
foreach (String image in imageNames)
{
Uri source = new Uri("ms-appx:///" + image);
ImageSource imgSource = new BitmapImage(source);
Image myImage = new Image();
myImage.Source = imgSource;
gallery.Children.Add(myImage);
}
The above code gets all the images from the gallery folder and adds them to a variablesizedwrapgrid. I want to add a click event on each of these (to basically allow a user to save them to the device they are using)
Thanks
1)
myImage.PointerReleased += Img_PointerReleased;
private void Img_PointerReleased(object sender, PointerRoutedEventArgs e)
{
// do your job
}
2) or write UserControl wrapping Image that inherits from Button and add proper VisualStates if you don't want to have default button animations - this way you will be able to use Clicked event

Windows phone create animation of controls

I need to load some images and show on grid (with simple animation). I have
Image img = IconWithId(i);
// set some properties
//...
img.Tap += img_Tap;
img.ImageOpened += img_ImageOpened;
gameView.Children.Add(img);
In event img_ImageOpened i create animation
void img_ImageOpened(object sender, RoutedEventArgs e)
{
Image img = sender as Image;
Storyboard story = new Storyboard();
DoubleAnimation dAnimation = new DoubleAnimation();
dAnimation.From = 0;
dAnimation.To = 1;
dAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(100));
Storyboard.SetTarget(dAnimation, img);
Storyboard.SetTargetProperty(dAnimation, new PropertyPath(OpacityProperty));
story.Children.Add(dAnimation);
story.Begin();
}
I think i have animation which should show image but it don't work. Image loaded without animation. What can i do?
PS i need to animation when images will close. I think to use event unloaded
Sorry for my english
I tested your code on a Windows Phone 8 with Phone 8 SDK
Your code works perfectly fine.
You need to change the duration to a longer period. 100ms way too fast. You won't be able to see it quick enough.
Change it to something longer like this
dAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(5000));

Resizing custom user control according to data in the webBrowser control docked in it

I have a webBrowser control named webBrowser1 that is added and docked as DockStyle.Full on a custom user control. The web-browser accepts some HTML text dynamically and displays it. I disabled the scroll bars of the webBrowser control. My problem is that whenever the content is somewhat lengthy, the webBrowser hides it from below. But the requirement of my project objective is that the webBrowser must not show either scroll bars or it should not hide some of the content. The content must be completely shown as it is without scrolling. That means the user control on which the webBrowser is docked must resize itself according to webBrowser's content. So, can anyone please suggest me how to achieve this? I searched all over the internet and SO but found nothing.
You can get the current size of HTML window via WebBrowser.Document.Window.Size and resize the container control accordingly. Depending on how your WebBrowser control content receives dynamic updates, you'd probably need to do this after each update. You could also try WebBrowser.Document.Body.ScrollRectangle if Document.Window.Size doesn't grow in the expected way.
[EDITED] The following code works for me (IE10):
private void Form1_Load(object sender, EventArgs e)
{
this.BackColor = System.Drawing.Color.DarkGray;
this.webBrowser.ScrollBarsEnabled = false;
this.webBrowser.Dock = DockStyle.None;
this.webBrowser.Location = new System.Drawing.Point(0, 0);
this.webBrowser.Size = new System.Drawing.Size(320, 200);
DownloadAsync("http://www.example.com").ContinueWith((task) =>
{
var html = task.Result;
MessageBox.Show(String.Format(
"WebBrowser.Size: {0}, Document.Window.Size: {1}, Document.Body.ScrollRectangle: {2}\n\n{3}",
this.webBrowser.Size,
this.webBrowser.Document.Window.Size,
this.webBrowser.Document.Body.ScrollRectangle.Size,
html));
this.webBrowser.Size = this.webBrowser.Document.Body.ScrollRectangle.Size;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
async Task<string> DownloadAsync(string url)
{
TaskCompletionSource<bool> onloadTcs = new TaskCompletionSource<bool>();
WebBrowserDocumentCompletedEventHandler handler = null;
handler = delegate
{
this.webBrowser.DocumentCompleted -= handler;
// attach to subscribe to DOM onload event
this.webBrowser.Document.Window.AttachEventHandler("onload", delegate
{
// each navigation has its own TaskCompletionSource
if (onloadTcs.Task.IsCompleted)
return; // this should not be happening
// signal the completion of the page loading
onloadTcs.SetResult(true);
});
};
// register DocumentCompleted handler
this.webBrowser.DocumentCompleted += handler;
// Navigate to url
this.webBrowser.Navigate(url);
// continue upon onload
await onloadTcs.Task;
// the document has been fully loaded, can access DOM here
// return the current HTML snapshot
return ((dynamic)this.webBrowser.Document.DomDocument).documentElement.outerHTML.ToString();
}
To resize your usercontrol you first need to get the size needed by the content. This can be achived with TextRender.MeasureText, like so:
public static int GetContentHeight(string content, Control contentHolder, Font contentFont)
{
Font font = (contentFont != null) ? contentFont : contentHolder.Font;
Size sz = new Size(contentHolder.Width, int.MaxValue);
int padding = 3;
int borders = contentHolder.Height - contentHolder.ClientSize.Height;
TextFormatFlags flags = TextFormatFlags.WordBreak;
sz = TextRenderer.MeasureText(content, contentHolder.Font, sz, flags);
int cHeight = sz.Height + borders + padding;
return cHeight;
}
In your case it's a bit more tricky, as the text contains HTML-tags wich needs to be filtered away, to get the correct height.. I belive this can be achived with RegEx or a simple algo wich removes all content between < and > from a string.. You may also have to create special handlig for some HTML-tags (I.E Lists)

Display loading while Caching image from URL

I have a code in WPF C# that i use to load images from the web as such:
if (myImgURL != "")
{
var imgBitmap = new BitmapImage();
imgBitmap.BeginInit();
imgBitmap.UriSource = new Uri(myImgURL, UriKind.RelativeOrAbsolute);
imgBitmap.CacheOption = BitmapCacheOption.OnLoad;
imgBitmap.EndInit();
myImgControl.Source = imgBitmap;
}
It works perfectly but sometimes it takes a while before the images get displayed (if internet is slow and all). How can I have a ProgressRing (from the Mahapps.Metro toolkit) display and be enabled while the image loads and then disappear when the image is displayed?
I am not aware of any event trigger for when an image is being downloaded and when it is fully loaded.
Take a look at the following events in class BitmapSource (the base class of BitmapImage):
DownloadProgress
DownloadCompleted
DownloadFailed
And just a note. You are creating a BitmapImage from an Uri and showing it immediately. Hence there is no need to set BitmapCacheOption.OnLoad (which afaik is necessary only if you load from a stream that should be closed immediately after EndInit). So you could shorten your code like this:
if (!string.IsNullOrEmpty(myImgURL))
{
var imgBitmap = new BitmapImage(new Uri(myImgURL));
myImgControl.Source = imgBitmap;
if (imgBitmap.IsDownloading)
{
// start download animation here
imgBitmap.DownloadCompleted += (o, e) =>
{
// stop download animation here
};
imgBitmap.DownloadFailed += (o, e) =>
{
// stop download animation here
};
}

Categories