In my WPF I want images on the screen to change, every time when the user clicks right button. The problem is that I have all the time same error message:
'Invalid URI: The format of the URI could not be determined.'
This is the code:
string pic1 = #"C:/Users/Milk/Desktop/exercises/wpf_1/portraits/1.png";
string pic2 = #"C:/Users/Milk/Desktop/exercises/wpf_1/portraits/2.png";
private void buttonRight_Click(object sender, RoutedEventArgs e)
{
List<string> portraits = new List<string>();
portraits.Add(pic1);
portraits.Add(pic2);
string ShowPicture = portraits[counter % portraits.Count];
image.Source = new BitmapImage(new Uri(portraits.ToString()));
counter++;
}
When I tried just with one string, like this:
image.Source = new BitmapImage(new Uri(pic1));
it was working fine, but once it's in the list, it cannot find the file path - at least, that's how this looks like for me.
Any idea how to fix this and where I am making an error?
It is because .ToString() usually returns namespace of an object (unless overriden), which in this case is List's namespace; you need to pass in actual list values one by one into Uri constructor.
What you need to do is to pass in actual path as such:
string ShowPicture = portraits[counter % portraits.Count];
image.Source = new BitmapImage(new Uri(ShowPicture));
Hi you are linking it to the list Object and not the element inside the list
This should solve your issue :
image.Source = new BitmapImage(new Uri(portraits[0].ToString()));
that will get the pic1
and if you want to get the pic2
you will need to write :
image.Source = new BitmapImage(new Uri(portraits[1].ToString()));
if you want to get both of pic you need to add a loop
Something like :
for (int i=0 ; i < portraits.count ; i++)
image.Source = new BitmapImage(new Uri(portraits[i].ToString()));
//..Do the rest
portraits , let me know exactly your expected result and I will add further details
Related
I am trying add a background image using the image property in button. The issue I'm facing is that i can't set StreamImageSource as button background. I encountered the error given below if I try to do so.
The Code I use to set Image:
ImageSource iconsource =ImageSource.FromStream(() => new MemoryStream(ImgASBytes));
Button Icon = new Button ();
Icon.Image = iconsource ;
The Error I encounter:
Error CS0266: Cannot implicitly convert type 'Xamarin.Forms.ImageSource' to 'Xamarin.Forms.FileImageSource'. An explicit conversion exists (are you missing a cast?)
ImageSource.FromStream () returns a StreamImageSource (see docs). Button.Image accepts only FileImageSource (see docs).
It means that what you're trying to achieve won't work, no matter how hard you try to cast one into the other.
Button.Image will accept images stored as resources in your platform projects, and loaded either with:
Icon.Image = ImageSource.FromFile ("foobar.png");
or
Icon.Image = "foobar.png";
The accepted answer is true that you can't cast StreamImageSource to FileImageSource, I think that the real question is about how to share images in a PCL and use them on a button, just like one would when creating an Image forms control.
The answer is to have a Grid which contains both a Button and an Image object, where the Image overlaps the Button.
For example, the C# code might look like this:
ImageSource imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
Button iconButton = new Button ();
iconButton.VerticalOptions = LayoutOptions.FillAndExpand;
iconButton.HorizontalOptions = LayoutOptions.FillAndExpand;
var image = new Image();
image.Source = imageSource;
// So it doesn't eat up clicks that should go to the button:
image.InputTransparent = true;
// Give it a margin so it doesn't extend to the edge of the grid
image.Margin = new Thickness(10);
var grid = new Grid();
// If we don't set a width request, it may stretch horizontally in a stack
grid.WidthRequest = 48;
// Add the button first, so it is under the image...
grid.Children.Add(iconButton);
// ...then add the image
grid.Children.Add(image);
You may have to play with the sizes and thickness values but this should get you a clickable button with an icon.
As of Xamarin.Forms 3.4.0 you can now use ImageButton. You can use embedded images by using an extension method explained in this MS document
Careful with upper- and lowercase in filenames.
I was wondering, why my button-images were shown properly on the simulator, but not on my iPhone.
On the device the filename must match exactly, the simulator doesn't care about upper- and lowercase in filenames.
I use this and it works
var imageA = new Image();
imageA.Source=(FileImageSource)ImageSource.FromFile(allergeneLocation)};
or
var imageA = new Image()
{
BackgroundColor = Color.Teal,
Source = (FileImageSource)ImageSource.FromFile(allergeneLocation)},
};
Here is what I tried:
Button refreshBut = new Button
{
Image = (FileImageSource)
(ImageSource.FromFile("refreshBut.png"))
};
While it compiles I then get an unhandled null reference exception with the description: Object reference not set to an instance of an object. I am not sure if this will help anyone else try to solve this but I am at the same wall.
how do i set a buttons name when i created it in c# so i can call it later?
i have a a List of strings (Commands).
i loop over it an create a button for each item in the List.
commands.ForEach(delegate (String i)
{
Button button = new Button()
{
Name = i,
Tag = i,
MaxWidth = 50,
MaxHeight = 50,
BorderBrush = null
};
button.Click += new RoutedEventHandler(button_Click);
this.grid.Children.Add(button);
Uri resourceUri = new Uri("led_Off.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button.Background = brush;
});
This loop works fine until i add the line
Name = i
i am in a spot where these buttons were created and i now need to change some of there back ground images.
is there a better way to call them then by there name?
Name should be a valid string: try Name = "button" + i.ToString() (FYI, Button Name cannot be just "1", it's an invalid Name). Also, Tag =i.ToString(). Hope this may help
Don't do it, use data binding and data templating with commands instead.
There is no reason to ever create any UI elements in a loop in WPF.
Edit: Just this.
I have recently started learning Windows phone app development with no c# knowledge, and I wanted to make an app that displays a random image on the ImageBox when the button is clicked.
How will I go about making a random image (from a list) come up every time the user presses the button?
Here is all I have so far:
myImage.Source = new BitmapImage(new Uri("/Images/Pic1.png", UriKind.Relative));
If you have a list of images, or an image naming convention, then this is easy.
For example, if your images are named "Pic1" through "Pic10", then just use:
const int numberOfImages = 10;
var rand = new Random();
int imageNumber = rand.Next(numberOfImages) + 1;
string imageName = string.Format("/Images/Pic{0}.png", imageNumber);
myImage.Source = new BitmapImage(new Uri(imageName, UriKind.Relative));
Or if you have an array with the names of available images:
string[] imageNames = { "Pic1.png", "AnotherPic.png" };
var rand = new Random();
string imageName = imageNames[rand.Next(imageNames.Length)];
string imageName = string.Concat("/Images/", imageName);
myImage.Source = new BitmapImage(new Uri(imageName, UriKind.Relative));
Edit
It is more tricky than you might think to enumerate "Resource" images at runtime. See here for a discussion of this topic.
Edit #2
Actually, one of the answers from the above link has a nifty approach -- use a T4 template to generate the list of images at compile time.
I am struggling to teach myself C#, and long googling has not turned up this answer:
I have a classes Rom, Game and Art. Rom.Game.Art is for images and is defined thus:
public class art
{
public Image Screen { get; set; }
public Image Marquis { get; set; }
public Image Logo { get; set; }
public art ()
{
BitmapImage Default_image = new BitmapImage();
Default_image.BeginInit();
Default_image.UriSource = new Uri(#"C:\Users\Major Major\Documents\Visual Studio 2013\Projects\Robin\Robin\images\bee_ace.png", UriKind.Absolute);
Default_image.EndInit();
this.Screen = new Image();
this.Screen.Source = Default_image;
this.Marquis = new Image();
this.Marquis.Source = Default_image;
this.Logo = new Image();
this.Logo.Source = Default_image;
}
}
I want to create an array of Roms, and populate the many nested properties and subclasses from a DataTable in a loop. Before I get into the loop, though, I just want to get a block of test code to work. The following works just fine:
InitializeComponent();
BitmapImage Image_0 = new BitmapImage();
Image_0.BeginInit();
Image_0.UriSource = new Uri(#"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute);
Image_0.EndInit();
ROMS.Insert(0, new Rom());
ROMS[0].Name = "Congo Bongo";
ROMS[0].Game.Art.Screen.Source = Image_0;
ROMS[0].Game.Date = "1983";
ROMS[0].Game.Platform = "Intellivision";
ROM_list.ItemsSource = ROMS;
My complaint is that, if I put this in a loop, all of the images in the array will be the same--they will be the last image entered. It seems the expression "ROMS[0].Game.Art.Screen.Source = Image_0;" ties ROMS[0].Game.Art.Screen.Source to the variable Image_0, rather than just transferring the value (this seems like surprising behavior to me, but no worries). So that in order to keep populating ROMS[j].Game.Art.Screen.Source, I have to create an array of BitmapImages separate from the ROM array as a reference. What I'd prefer is to instantiate(?) the BitmapImages within the array, like this:
ROMS[0].Game.Art.Screen.Source = new BitmapImage();
InitializeComponent();
ROMS[0].Game.Art.Screen.Source.BeginInit();
ROMS[0].Game.Art.Screen.Source.UriSource = new Uri(#"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute);
ROMS[0].Game.Art.Screen.Source.EndInit();
This doesn't work. Rom.Game.Art.Screen.Source is not a BitMapImage, and I cannot find the methods to assign an image to it.
So my questions, specifically:
1. Is there a way to assign an image source to ROMS[0].Game.Art.Screen.Source without creating a separate BitmapImage that lives on separately, or is that stupid?
Is there a smarter way to do what I'm trying to do?
Is there a reference to help me understand the relationships between the myriad image classes in C#?
Sorry for the wordy question, and thanks.
I think you should do some review about DataBinding. You will save more time.
You just need create something like the models:
ROM.Game.Art.Screen.Path ="meuPath.Jpg";
myItemSource = ROMS;
and in the end, do something like:
<ItemsControl x:Name="myItemSource">
<TextBlock Text="{Binding ROM.Game.Art.Screen.Name}"/>
<Image Source="{Binding ROM.Game.Art.Screen.Path,Converter=MyConverterImageToPath"/>
</ItemsControl>
You need to create a new instance of the BitMapImage for each of your array member. C# uses references if you assign an object to a variable.
ROMS[0].Game.Art.Screen.Source = Image_0;
here you are creating a reference to Image_0, if you do now something like ...
ROMS[1].Game.Art.Screen.Source = Image_0;
both roms[0] and roms[1] .screen.source referencing Image_0. If you do now something like:
ROMS[0].Game.Art.Screen.Source.UriSource = new Uri(#"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute);
you update Image_0 and all your rom.screen.source are referencing to Image_0 and are updated
If you want to use Image_0 as base "image" for all, what you could do is call the .Clone() function of the bitmapImage, which creates a deep copy of the object (a new object, instead of a reference).
So somewhere in the begin you have:
InitializeComponent();
BitmapImage Image_0 = new BitmapImage();
Image_0.BeginInit();
Image_0.UriSource = new Uri(#"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute);
Image_0.EndInit();
in your loop you have then
ROMS[i].Name = "Congo Bongo";
ROMS[i].Game.Art.Screen.Source = Image_0.Clone();
ROMS[i].Game.Date = "1983";
ROMS[i].Game.Platform = "Intellivision";
Thanks a lot for looking at this.
The deep copy concept is instructive, and gets me on the right track. But there is still no method that lets me modify ROMS[i].Game.Art.Screen.Source (the class of this Is Image.Source). It's interesting that I can assign a BitmapImage directly to an Image.Source, but then I cannot alter the BitmapImage by going through the class nest. In other words
ROMS[1].Game.Art.Screen.Source.UriSource
does not exist, even though ROMS[1].Game.Art.Screen.Source was set equal to a BitmapImage, which has a .UriSource.
So, using you comments as a starting point, I came up with the following, which will work in a loop, obviously with loop variables in place of each string:
InitializeComponent();
ROMS.Insert(0, new Rom());
ROMS.Insert(1, new Rom());
ROMS[0].Name = "Congo Bongo";
ROMS[0].Game.Art.Screen.Source = new BitmapImage(new Uri(#"E:\Arcade\Art\Box\Intellivision\Congo Bongo.jpg", UriKind.Absolute));
ROMS[0].Game.Date = "1983";
ROMS[0].Game.Platform = "Intellivision";
ROMS[1].Name = "Donkey Kong";
ROMS[1].Game.Art.Screen.Source = new BitmapImage(new Uri(#"E:\Arcade\Art\Box\Intellivision\Donkey Kong.jpg", UriKind.Absolute));
ROMS[1].Game.Date = "1982";
ROMS[1].Game.Platform = "Intellivision";
ROM_list.ItemsSource = ROMS;
Still, I have to create a new BitMapImage and Uri every time I modify Game.Image.Source. I wonder what happens to the old BitMapImage and Uri, which don't even have names and can't be modified. Do they just float around in memory for eternity, haunting the living variables? Am I still doing something silly?
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.