I have a problem about C# file name. I show some pictures with PictureBox. Also I want to write picture's name in a TextBox. I search fileinfo, directoryinfo, but it doesnt work.
List<Image> images = new List<Image>();
images.Add(Properties.Resources.baseball_bat);
images.Add(Properties.Resources.bracelet);
images.Add(Properties.Resources.bride);
pictureBox1.Image = images[..];
and i want to write baseball_bat, bride, bracelet etc. in a TextBox. What can I do? any offer?
Well, one of the simplest methods is saving both the name and the image in a List<KeyValuePair<string,Image>> or IDictionary<string,image>.
Here's an example using a IDictionary<string,image>
(I decided for SortedList<> because of the indexing) :
var images = new SortedList<string, Image>();
images.Add("baseball_bat", Properties.Resources.baseball_bat);
images.Add("bracelet", Properties.Resources.bracelet);
...
// when you show the first image...
pictureBox1.Image = images.Values[0];
textBox1.Text = images.Keys[0];
// when you show the nth image...
pictureBox1.Image = images.Values[n];
textBox1.Text = images.Keys[n];
For a List<KeyValuePair<string,Image>> would be:
var images = new List<KeyValuePair<string, Image>>();
images.Add(new KeyValuePair<string,Image>("baseball_bat", Properties.Resources.baseball_bat));
images.Add(new KeyValuePair<string,Image>("bracelet", Properties.Resources.bracelet));
...
// when you show the first image...
pictureBox1.Image = images[0].Values;
textBox1.Text = images[0].Keys;
// when you show the nth image...
pictureBox1.Image = images[n].Values;
textBox1.Text = images[n].Keys;
This functionality is already built in...
Image lists store their images in a way that you can reference them by name and return the image.
Single use :
private string GetImageName(ImageList imglist, int index)
{
return imglist.Images.Keys[index].ToString();
}
This returns the name of the image at the passed index
Store values for later on :
private Dictionary<int, string> GetImageNames(ImageList imglist)
{
var dict = new Dictionary<int, string>();
int salt = 0;
foreach (var item in imglist.Images.Keys)
{
dict.Add(salt, item.ToString());
salt++;
}
return dict;
}
This returns a dictionary that references the index of picture to their string name in the image list.
Once again this is built in there is no need to try to extend funct. to it...
You can get all the resources along with their keys (names of the resources) by using reflection:
//a helper dictionary if you want to save the images and their names for later use
var namesAndImages = new Dictionary<String, Image>();
var resourcesSet = Properties.Resources.ResourceManager.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);
foreach (System.Collections.DictionaryEntry myResource in resourcesSet)
{
if (myResource.Value is Image) //is this resource is associated with an image
{
String resName = myResource.Key.ToString(); //get resource's name
Image resImage = myResource.Value as Image; //get the Image itself
namesAndImages.Add(resName, resImage);
}
}
//now you can use the values saved in the dictionary and easily get their names
...
Update: I've updated the code to save the values in a dictionary, so you can conveniently use them later.
Related
I have create a image box which changes the image within it when it is click. It is stored in form A. I now have a form b. I would like to check in form b. if the image in the picture box in form A is equal to a specific image then change the image in a picturebox in form B.
I am have problems accessing the pic box in form A due to I think it being private.
Despite the apparent simple nature of the problem, the correct way to accomplish this is deceptively complex. You may want to rethink the architecture of your application to perform this check another way, such as with an associated ID number or UUID. However, if you do in fact need to perform a content equality check on images in this manner, as follows is a basic solution that I have tested.
Since it would be painfully inefficient for us to directly compare two images to determine their equality, the best solution is to implement a simple hashing algorithm and check that instead. This is the most complicated part of the solution. To perform this automatically and abstract this step away, we can create a simple wrapper class around the standard Image object as follows:
public class ComparableImage
{
public Image Image
{
get { return this.image; }
set { SetImage(value); }
}
public string SHA1
{
get { return this.sha1; }
}
private Image image = null;
private string sha1 = string.Empty;
// This is the important part that lets us
// efficiently compare two images:
public override bool Equals(object image)
{
if ((image != null) && (image is ComparableImage) )
{
return (sha1.Equals(((ComparableImage)image).sha1));
}
else return false;
}
public override int GetHashCode()
{
return sha1.GetHashCode();
}
private void SetImage(Image image)
{
this.image = image;
this.sha1 = ComputeSHA1(image);
}
private static string ComputeSHA1(Image image)
{
if (image != null)
{
var bytes = GetBytes(image);
using (SHA1Managed SHA1 = new SHA1Managed())
{
return Convert.ToBase64String(SHA1.ComputeHash(bytes));
}
}
else return string.Empty;
}
private static byte[] GetBytes(Image image)
{
using (var stream = new MemoryStream())
{
image.Save(stream, ImageFormat.Bmp);
return stream.ToArray();
}
}
}
Using the above class, we can simply call the Equals method to find out if two images are equal in content, without ever having to worry about anything further other than creating ComparableImage objects.
The next issue is exposing a public Image property from each of the forms which enables us to access an instance of ComparableImage. We can easily accomplish this using the following pattern:
public class ComparableImageForm : Form
{
// This is the property we need to expose:
public ComparableImage Image
{
get { return this.image; }
set { SetImage(value); }
}
private ComparableImage image;
private PictureBox pictureBox = new PictureBox()
{
Dock = DockStyle.Fill
};
public ComparableImageForm()
{
this.Controls.Add(pictureBox);
}
// For clarity, we are also setting a picture box image
// from the ComparableImage when it is assigned:
private void SetImage(ComparableImage image)
{
this.image = image;
pictureBox.Image = image.Image;
}
}
Finally, we are ready to load some images do some test comparisons:
// Load two images from file to compare.
// In practice, images can be loaded from anywhere,
// even from the designer.
var image1 = new ComparableImage()
{
Image = Image.FromFile("bitmap1.bmp")
};
var image2 = new ComparableImage()
{
Image = Image.FromFile("bitmap2.bmp")
};
// Create two forms that have picture boxes:
var formA = new ComparableImageForm()
{
Image = image1
};
var formB = new ComparableImageForm()
{
Image = image2
};
// Perform the check to see if they are equal:
if (formA.Image.Equals(formB.Image))
{
MessageBox.Show("The images are indeed equal.");
}
else
{
MessageBox.Show("The images are NOT equal.");
}
// Since images are compared based on their SHA1 hash,
// it does not matter where the image comes from as long
// as the data is the same. Here, we are loading another
// copy of 'bitmap1.bmp':
var anotherImage = new ComparableImage()
{
Image = Image.FromFile("bitmap1.bmp")
};
// The following statement will evaluate as true:
bool isEqual = (anotherImage.Equals(image1));
Thats it!
You should make an instance from your form B. search in controls of that form, find picturebox and change its properties. and show that instance everytime you want to show that form.
It's not a good idea to compare images to detect if they are the same.
It would be better to give every picture an unique ID and store that in a variable. Make sure both forms haven access to that variable, so you can compare it with the ID of the image in form2.
I call an API and get from there an id, a name and an URL for images...
I display them in a flipview and I used to convert them, saved them in a folder, convert them back and show them...
So I thought it would be much easier if I show them directly from their URL.
Now, when the user clicks (taps) on the image, it has to go to another page to show the detail of that image (and it was working fine, when saving the pic, since I named them by the id (id.png))
is there anyway I can name the ImageSource to be this id, or give it like a property (Title or Name)?
var pics = from special in GlobalVariables.Special
where special.special == "1"
select new { id = special.id, name = special.name, image = special.banner_image, featured = special.special };
foreach (var item in pics)
{
await savePicToDisk(item.image, item.name, item.id, item.featured);
}
So, then, instead of save them:
List<ImageSource> listOfImages = new List<ImageSource>();
string url = "http://52.8.2.140" + picAddress;
ImageSource urlOfPic = new BitmapImage(new Uri(url, UriKind.Absolute));
listOfImages.Add(urlOfPic);
Then, where I have to show them, I just bind it to the flipview:
flipView1.DataContext = Classes.Special.listOfImages;
The Item_Click event's arguments have a property ClickedItem (in some cases you may also need OriginalSource), which you can use to point to your item in a collection. If item's class has a property responsible for Name/Id/other you can freely pass that when navigating, other solution may be passing an index of selected item in the collection. Sample code;
private void ItemClick(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem as ItemClass;
if (item != null)
Frame.Navigate(typeof(DetailPage), item.ID);
// if your item contains a Name/Id/other you can pass that when navigating
// you can also pass index of your item in collection if you need
}
I'm trying too make a memory game.
In this game when a button is klicked the button and an picturebox will be send into a List.
I want too use the images inside the pictureboxes as a way too use this code. But even when the two images are the same the code wont work. Is there a way too check the image used like Name.jpg.
if(buttonCount == 2)
{
if(pictureList[0].Image == pictureList[1].Image)
{
buttonCount = 0;
buttonList.RemoveAt(0)
buttonList.RemoveAt(0);
pictureList.RemoveAt(0);
pictureList.RemoveAt(0);
}
}
You could save an Id of the image (or e.g. the filename like you suggested) in the Tag.
So when loading the image into the picture box:
string path = "PATH";
pictureBox.Image = Image.FromFile(path);
pictureBox.Tag = path;
Then you could compare the Tag.
BUT I think (show us how you load the images please) this is not working as it is, because you load the image twice from the disk like:
pictureBox1.Image = Image.FromFile(path);
pictureBox2.Image = Image.FromFile(path);
Because then you have differen instances and so the equals returns false.
If you do it like the following it should also work:
var image = Image.FromFile(path);
pictureBox1.Image = image;
pictureBox2.Image = image;
In your current application, you do not have enough information associated with the image object to identify it. As such, you need to possibly extend the Image class to include this information or store it in some other way for comparison.
Extending Image class
public class GameImage : Image
{
public static GameImage GetImage(string filename)
{
GameImage img = (GameImage)Image.FromFile(filename);
img.FileName = filename;
return img;
}
public string FileName { get; private set; }
}
Then the comparison becomes
if(buttonCount == 2)
{
if(((GameImage)pictureList[0].Image).FileName == ((GameImage)pictureList[1].Image).FileName)
{
buttonCount = 0;
buttonList.RemoveAt(0)
buttonList.RemoveAt(0);
pictureList.RemoveAt(0);
pictureList.RemoveAt(0);
}
}
Note: Note tested!
How to add a parameter for an image to this variable?
var selectionDisplay = new SelectionDisplay(button.Label as string);
Thanks in advance!
EDIT:
I have this set of images and their respective code below (see pic1)
This is where the program gets the images to be displayed. The code for the buttons is this one:
var files = Directory.GetFiles(#".\GalleryImages");
foreach (var file in files)
{
FileInfo fileInfo = new FileInfo(file);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(file, UriKind.Relative);
bi.EndInit();
var button = new KinectTileButton
{
Label = System.IO.Path.GetFileNameWithoutExtension(file),
Background = new ImageBrush(bi)
};
this.wrapPanel.Children.Add(button);
}
This is where the program gets the images to be displayed.
The code for the buttons is this one:
private void KinectTileButtonclick(object sender, RoutedEventArgs e)
{
var button = (KinectTileButton)e.fake_fake_fakeource;
var selectionDisplay = new SelectionDisplay(button.Label as string);
this.kinectRegionGrid.Children.Add(selectionDisplay);
e.Handled = true;
Right now, when i click on of the images, the SelectionDisplay window pops up, which look like this (see pic2). What i want is that when I click an image the SelectionDisplay window should open with the respective image... meaning that if I click on the image with a dog, the window should open with the dog's image, not with other image.
I hope I've made myself clear and that you can help me.
http://i58.tinypic.com/8zl6h3.jpg
http://i57.tinypic.com/208fosy.png
is this the constructor you are talking about? is this where i should make changes? should i add something after "string itemid"?
public SelectionDisplay(string itemId)
{
this.InitializeComponent();
this.messageTextBlock.Text = string.Format(CultureInfo.CurrentCulture,Properties.Resources.SelectedMessage,itemId);
}
I see two approaches:
Just pass the image brush in your constructor. Its view->view, so you aren't breaking MVVM (and it looks like you aren't using that pattern anyways).
new SelectionDisplay(button.Label, button.Background);
Set the path as the "tag" of the button. The tag property is an object you can put whatever you want into (the framework does not use it, and so it is included for this very purpose). Then just pass the string to SelectionDisplay, and instantiate the image just like you are doing for the button:
var button = new KinectTileButton
{
Label = System.IO.Path.GetFileNameWithoutExtension(file),
Background = new ImageBrush(bi),
Tag = file
};
var selectionDisplay = new SelectionDisplay(button.Label as string, button.Tag as string);
FrameworkElement.Tag on MSDN (Note that Button derives from FrameworkElement, as do all controls, so it automatically has it as well!)
UPDATE
I see that SelectionDisplay is a UserControl in your project, so you just need to change its constructor to look like:
Numbers match above:
SelectionDisplay(string labelText, ImageBrush sourceImage)
SelectionDisplay(string labelText, string imagePath)
That is the source of the error you are getting, you have to modify the constructor to take the new parameter.
Please let me know if I can clarify anything.
C#'s ListView has the follow add methods available for adding an entry
public virtual ListViewItem Add(ListViewItem value)
public virtual ListViewItem Add(string text)
public virtual ListViewItem Add(string text, int imageIndex)
public virtual ListViewItem Add(string text, string imageKey)
public virtual ListViewItem Add(string key, string text, int imageIndex)
public virtual ListViewItem Add(string key, string text, string imageKey)
Scenario: I have a ListView and wish to dynamically add ListViewItems with their own unique images in the first column. Furthermore these images can be updated depending upon state changes
Question: How would you do you do this?
Code I'm working with
private void AddToMyList(SomeDataType message)
{
string Entrykey = message.ID;
//add its 1 column parameters
string[] rowEntry = new string[1];
rowEntry[0] = message.name;
//make it a listviewItem and indicate its row
ListViewItem row = new ListViewItem(rowEntry, (deviceListView.Items.Count - 1));
//Tag the row entry as the unique id
row.Tag = Entrykey;
//Add the Image to the first column
row.ImageIndex = 0;
//Add the image if one is supplied
imagelistforTypeIcons.Images.Add(Entrykey, message.marker.markerIcon);
//finally add it to the device list view
typeListView.Items.Add(row);
}
There are two things you need to do
Add image to ImageList if it isn't already in it
Create new ListViewItem and assign image from previous point to it
It could go like this, based on your code:
// Add markerIcon to ImageList under Entrykey
imagelistforTypeIcons.Images.Add(Entrykey, message.marker.markerIcon);
// Use icon from ImageList which is stored under Entrykey
ListViewItem row = new ListViewItem(rowEntry);
row.ImageKey = Entrykey;
// Do whatever else you need afterwards
row.Tag = Entrykey;
....
Problem with code in your question (without actually trying it out) looks to be in ImageIndex you are assigning.
you are adding new image to one image list, but assigning an image to ListViewRow from a different one
you are providing image index in constructor but setting it to 0 afterwards (why?)
you are providing wrong image index in the first place, because you calculated index of last image in the image list, before adding the new image.
So your code could also be fine like this:
// Add markerIcon to ImageList under Entrykey
imagelistforTypeIcons.Images.Add(Entrykey, message.marker.markerIcon);
// Use icon from ImageList which is stored under Entrykey
ListViewItem row = new ListViewItem(rowEntry);
row.ImageIndex = imagelistforTypeIcons.Items.Count - 1;
// Do whatever else you need afterwards
row.Tag = Entrykey;