|
I have an idea for a program using the picture viewer control. I would like to have a label at the top of the form that says "Choose a photo of the musicians listed below to see a photo."
Then below that I would make four option buttons. And next to each option button put a musician's name.
Then below that on the bottom have two buttons. One buttons says "Show photo." The other button says "Clear image."
Problem is all the Youtube videos I've seen that demonstrate the picture box have you using open file dialog and it looks like you have to manually browse into the folder on your drive to select the photo.
I don't want to do that. I want my program to be automatic. No browsing for a photo. You select an option and then hit the button "Show photo" and the program shows the photo in the viewer.
But I don't know if this is possible so let me know please.
|
|
|
|
|
Yes, it's possible: you do not need to use a OpenFileDialog to access the image, that just provides you with a path to the file.
If you want to load the file from a specific location, then you can just specify that:
byte[] data = File.ReadAllBytes(@"D:\Temp\MyImage.bmp");
MemoryStream ms = new MemoryStream(data);
Image im = Image.FromStream(ms); Or you can load from the application EXE folder:
byte[] data = File.ReadAllBytes(@".\MyImage.bmp");
MemoryStream ms = new MemoryStream(data);
Image im = Image.FromStream(ms); This has disadvantages in that you can't modify the image reliably as the folder is likely to be read only in production.
Or you can add the image as a resource and embed it in your application:
Image im = Properties.Resources.MyImage; And now you can't change the image from run to run of your app at all because it is part of your application EXE file.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Thanks. But I wish I understood what those lines of code mean. The only thing I understand is where you added the path to the image. That makes sense. But byte[] data and File.ReadAllBytes I don't know the why of that.
And I don't know what MemoryStream ms is either.
If you could perhaps explain what these lines do I would appreciate it.
|
|
|
|
|
Oh come on! Are you trying to run before you can walk? This is pretty basic stuff!
You know what a byte[] is, don't you? It's an array of bytes, is all. So what do you think that File.ReadAllBytes does? And if you don't understand what a function does, look it up in the official documentation: File.ReadAllBytes(String) Method (System.IO) | Microsoft Docs[^]
The next two are there for a specific reason: while you can load an image directly from a file, that locks the file until the image is Disposed - so if you want to write a modified version back to the file in your app, you can't. Converting the data to a Stream gets round that, by locking the Stream instead of the file. And if you don't understand what a Stream is then how on earth are you doing any file input / output?
So those three lines do this:
1) Read the disk-based image file into an array of bytes.
2) Construct a memory-based Stream from the array.
3) Create an Image from the Stream.
Seriously, if you don't understand stuff like this, then you need to re-read your course notes from the beginning, because you have missed a heck of a lot of useful stuff!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Come on now. I only program as a hobby. I've only done console programs so far. There is a lot of stuff I have not done. You programmers need to have some more understanding of what it's like not to be a full time developer.
If you came to me for guitar lessons I too could slice you to ribbons for all that you don't know. But that is a very poor way of teaching guitar.
Why would I need a byte array anyway. Just load the photo into the viewer. My photos will not be changing.
|
|
|
|
|
Dioxazine wrote: If you came to me for guitar lessons I too could slice you to ribbons for all that you don't know.
Yes, because I know nothing.
Dioxazine wrote: But that is a very poor way of teaching guitar.
And so is what you are doing.
Suppose I came to you for help with my guitar playing, and told you that I was learning on my own by guessing what to do and wondering why I can't play as fast as others - but the forks and spoons I jam under the frets to select the notes to strum take me too long to pull out and move?
Clearly, I don't know enough to play the guitar because I've spent so long guessing what to do instead of sitting down and actually learning the right way!
And that's where you are with development. You've found code that does some of what you want, but you don't understand how it works - or even exactly what it is doing - so you can't change it to do something else yourself. And for the same reasons as me with my guitar spoons - they work for me, but not very well - I need to be taken back to the beginning and learn how to play in a structured way that introduces chords and so on in a logical progression.
Seriously, even as a hobby this is a complicated subject and it really benefits from learning the basics thoroughly before you try to rush ahead to "more interesting" projects.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Why do you need stream to load picture into viewer?
Just imagine this:
You(stream) are necessary to play(load) a song(picture) at your guitar(viewer).
|
|
|
|
|
You should just use a "picture viewer". Something like MS Photo. It illustrates concepts such as files and folders.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
Hi,
I want to save all of my DataGridView content directly into a SQL server. I'm Using SQL Light Compact 4.0
All codes related to save function are in a button:
<pre> private void btnSave_Click(object sender, EventArgs e)
{
SqlCeConnection connection = new SqlCeConnection();
connection.ConnectionString = @"Data Source=C:\Users\Dell\Desktop\DataGridView\PMinfo.sdf";
SqlCeCommand myCommand = new SqlCeCommand();
myCommand.Connection = connection;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
myCommand.CommandText = @"INSERT into [PMinfo] (Number, CostCenter, pType, ServiceType, Receiver, WorkCenter, Start, End, Remaining, Status, ReceiveDate) values(@Number, @CostCenter, @pType, @ServiceType, @Receiver, @WorkCenter, @Start, @End, @Remaining, @Status, @ReceiveDate)";
myCommand.Parameters.AddWithValue("@Number", dataGridView1.Rows[i].Cells[0].Value.ToString());
myCommand.Parameters.AddWithValue("@CostCenter", dataGridView1.Rows[i].Cells[1].Value.ToString());
myCommand.Parameters.AddWithValue("@pType", dataGridView1.Rows[i].Cells[2].Value.ToString());
myCommand.Parameters.AddWithValue("@ServiceType", dataGridView1.Rows[i].Cells[3].Value.ToString());
myCommand.Parameters.AddWithValue("@Receiver", dataGridView1.Rows[i].Cells[4].Value.ToString());
myCommand.Parameters.AddWithValue("@WorkCenter", dataGridView1.Rows[i].Cells[5].Value.ToString());
myCommand.Parameters.AddWithValue("@Start", dataGridView1.Rows[i].Cells[6].Value.ToString());
myCommand.Parameters.AddWithValue("@End", dataGridView1.Rows[i].Cells[7].Value.ToString());
myCommand.Parameters.AddWithValue("@Remaining", dataGridView1.Rows[i].Cells[8].Value.ToString());
myCommand.Parameters.AddWithValue("@Status", dataGridView1.Rows[i].Cells[9].Value.ToString());
myCommand.Parameters.AddWithValue("@ReceiveDate", dataGridView1.Rows[i].Cells[10].Value.ToString());
connection.Open();
myCommand.ExecuteNonQuery();
connection.Close();
}
}
When I press the button, compiler gives error in line
myCommand.ExecuteNonQuery();
'There was an error parsing the query. [ Token line number = 1,Token line offset = 92,Token in error = End ]'
What is wrong with my code?
|
|
|
|
|
Alex Dunlop wrote: 'There was an error parsing the query. [ Token line number = 1,Token line offset = 92,Token in error = End ]'
It seems that the parser doesn't like the field name "End".
Try
myCommand.CommandText = @"INSERT into [PMinfo] (Number, CostCenter, pType, ServiceType, Receiver, WorkCenter, Start, [End], Remaining, Status, ReceiveDate) values(@Number, @CostCenter, @pType, @ServiceType, @Receiver, @WorkCenter, @Start, @End, @Remaining, @Status, @ReceiveDate)";
|
|
|
|
|
Thank you. solved.
When I keep the last column in DataGridView null, compiler give the following error in line
System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.NullReferenceException: 'Object reference not set to an instance of an object.'
I have check marked null properties for this column in SQL server.
|
|
|
|
|
Quote:
dataGridView1.Rows[i].Cells[10].Value.ToString() If the cell's Value is null , what do you think the result of calling the ToString method on the value will be?
Remove those .ToString() calls, and pass the cell values directly to the parameters.
myCommand.Parameters.AddWithValue("@Number", dataGridView1.Rows[i].Cells[0].Value);
myCommand.Parameters.AddWithValue("@CostCenter", dataGridView1.Rows[i].Cells[1].Value);
myCommand.Parameters.AddWithValue("@pType", dataGridView1.Rows[i].Cells[2].Value);
myCommand.Parameters.AddWithValue("@ServiceType", dataGridView1.Rows[i].Cells[3].Value);
myCommand.Parameters.AddWithValue("@Receiver", dataGridView1.Rows[i].Cells[4].Value);
myCommand.Parameters.AddWithValue("@WorkCenter", dataGridView1.Rows[i].Cells[5].Value);
myCommand.Parameters.AddWithValue("@Start", dataGridView1.Rows[i].Cells[6].Value);
myCommand.Parameters.AddWithValue("@End", dataGridView1.Rows[i].Cells[7].Value);
myCommand.Parameters.AddWithValue("@Remaining", dataGridView1.Rows[i].Cells[8].Value);
myCommand.Parameters.AddWithValue("@Status", dataGridView1.Rows[i].Cells[9].Value);
myCommand.Parameters.AddWithValue("@ReceiveDate", dataGridView1.Rows[i].Cells[10].Value);
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
That's not an SQL error - that's a C# error:
myCommand.Parameters.AddWithValue("@ReceiveDate", dataGridView1.Rows[i].Cells[10].Value.ToString());
If the cell value is null , you can't call ToString (or any other property / method) on it.
You could try
myCommand.Parameters.AddWithValue("@ReceiveDate", dataGridView1.Rows[i].Cells[10].Value?.ToString()); Depending on your C# version.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I added a line for clearing sql table before saving new data and then add new data. There are two problems:
private void btnSave_Click(object sender, EventArgs e)
{
update.PerformClick();
SqlCeConnection connection = new SqlCeConnection();
connection.ConnectionString = @"Data Source=C:\Users\Dell\Desktop\DataGridView\PMinfo.sdf";
SqlCeCommand myCommand = new SqlCeCommand();
myCommand.Connection = connection;
connection.Open();
myCommand.CommandText = "DELETE FROM PMinfo";
connection.Close();
myCommand.CommandText = @"INSERT into [PMinfo] (Number, CostCenter, pType, ServiceType, Receiver, WorkCenter, Start, [End], Remaining, Status, ReceiveDate) values(@Number, @CostCenter, @pType, @ServiceType, @Receiver, @WorkCenter, @Start, @End, @Remaining, @Status, @ReceiveDate)";
connection.Open();
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
myCommand.Parameters.AddWithValue("@Number", dataGridView1.Rows[i].Cells[0].Value);
myCommand.Parameters.AddWithValue("@CostCenter", dataGridView1.Rows[i].Cells[1].Value);
myCommand.Parameters.AddWithValue("@pType", dataGridView1.Rows[i].Cells[2].Value);
myCommand.Parameters.AddWithValue("@ServiceType", dataGridView1.Rows[i].Cells[3].Value);
myCommand.Parameters.AddWithValue("@Receiver", dataGridView1.Rows[i].Cells[4].Value);
myCommand.Parameters.AddWithValue("@WorkCenter", dataGridView1.Rows[i].Cells[5].Value);
myCommand.Parameters.AddWithValue("@Start", dataGridView1.Rows[i].Cells[6].Value);
myCommand.Parameters.AddWithValue("@End", dataGridView1.Rows[i].Cells[7].Value);
myCommand.Parameters.AddWithValue("@Remaining", dataGridView1.Rows[i].Cells[8].Value);
myCommand.Parameters.AddWithValue("@Status", dataGridView1.Rows[i].Cells[9].Value);
myCommand.Parameters.AddWithValue("@ReceiveDate", dataGridView1.Rows[i].Cells[10].Value);
myCommand.ExecuteNonQuery();
}
connection.Close();
}
1- Clearing table doesn't work.
2- When I can more than 1 rowsin DataGridView, compliler gives following error:
System.ArgumentException: 'The SqlCeParameter with this name is already contained by this SqlCeParameterCollection.'
I reviewed the loop but I couldn't find out the reason.
|
|
|
|
|
Alex Dunlop wrote: I reviewed the loop but I couldn't find out the reason
Hint: What do you suppose the "Add" part of "AddWithValue" might mean?
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
It adds a value to the end of the SqlParameterCollection.
|
|
|
|
|
And the error message is telling you "The SqlCeParameter with this name is already contained by this SqlCeParameterCollection"
Put the two together, and ...
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I think I need to put open and close parameters of sql inside the loop so in each iteration I open the sql write a row into sql table and close it and open it again and loop....
Am I right? Maybe I'd give it a try tomorrow.
modified 23-Nov-20 14:54pm.
|
|
|
|
|
See Dave's reply[^] below.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I solved it by adding
<pre lang="c#">myCommand.Parametes.Clear();
The final code:
private void btnSave_Click(object sender, EventArgs e)
{
update.PerformClick();
SqlCeConnection connection = new SqlCeConnection();
connection.ConnectionString = @"Data Source=C:\Users\Dell\Desktop\DataGridView\PMinfo.sdf";
SqlCeCommand myCommand = new SqlCeCommand();
myCommand.Connection = connection;
connection.Open();
myCommand.CommandText = "Delete From PMinfo";
myCommand.ExecuteNonQuery();
connection.Close();
myCommand.CommandText = @"INSERT into [PMinfo] (Number, CostCenter, pType, ServiceType, Receiver, WorkCenter, Start, [End], Remaining, Status, ReceiveDate) values(@Number, @CostCenter, @pType, @ServiceType, @Receiver, @WorkCenter, @Start, @End, @Remaining, @Status, @ReceiveDate)";
connection.Open();
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
myCommand.Parameters.Clear();
myCommand.Parameters.AddWithValue("@Number", dataGridView1.Rows[i].Cells[0].Value);
myCommand.Parameters.AddWithValue("@CostCenter", dataGridView1.Rows[i].Cells[1].Value);
myCommand.Parameters.AddWithValue("@pType", dataGridView1.Rows[i].Cells[2].Value);
myCommand.Parameters.AddWithValue("@ServiceType", dataGridView1.Rows[i].Cells[3].Value);
myCommand.Parameters.AddWithValue("@Receiver", dataGridView1.Rows[i].Cells[4].Value);
myCommand.Parameters.AddWithValue("@WorkCenter", dataGridView1.Rows[i].Cells[5].Value);
myCommand.Parameters.AddWithValue("@Start", dataGridView1.Rows[i].Cells[6].Value);
myCommand.Parameters.AddWithValue("@End", dataGridView1.Rows[i].Cells[7].Value);
myCommand.Parameters.AddWithValue("@Remaining", dataGridView1.Rows[i].Cells[8].Value);
myCommand.Parameters.AddWithValue("@Status", dataGridView1.Rows[i].Cells[9].Value);
myCommand.Parameters.AddWithValue("@ReceiveDate", dataGridView1.Rows[i].Cells[10].Value);
myCommand.ExecuteNonQuery();
}
connection.Close();
}
|
|
|
|
|
That's one way to do it, but it's the least performant and increases heap fragmentation.
Creating one set of parameter objects and reusing them is a much better method.
modified 25-Nov-20 0:59am.
|
|
|
|
|
What nobody mentioned is you are constantly adding new parameters to the SqlCommand.Parameters, on every pass of the loop.
You're not reusing parameters, you're creating new ones on every iteration of the loop. On the first iteration of the loop, your Parameters collection will have 11 parameters. On the second, 22 parameters. On the 3rd, 33 parameters...
Create the parameters OUTSIDE the loop, then just set the values inside.
SqlCeConnection connection = new SqlCeConnection();
connection.ConnectionString = @"Data Source=C:\Users\Dell\Desktop\DataGridView\PMinfo.sdf";
SqlCeCommand myCommand = new SqlCeCommand(@"INSERT into [PMinfo] (Number, CostCenter, pType, ServiceType, Receiver, WorkCenter, Start, End, Remaining, Status, ReceiveDate) values(@Number, @CostCenter, @pType, @ServiceType, @Receiver, @WorkCenter, @Start, @End, @Remaining, @Status, @ReceiveDate)");
myCommand.Connection = connection;
myCommand.Parameters.Add("@Number", SqlDbType.NVarChar);
myCommand.Parameters.Add("@CostCenter", ...);
myCommand.Parameters.Add("@pType", ...);
myCommand.Parameters.Add("@ServiceType", ...);
myCommand.Parameters.Add("@Receiver", ...);
myCommand.Parameters.Add("@WorkCenter", ...);
myCommand.Parameters.Add("@Start", ...);
myCommand.Parameters.Add("@End", ...);
myCommand.Parameters.Add("@Remaining", ...);
myCommand.Parameters.Add("@Status", ...);
myCommand.Parameters.Add("@ReceiveDate", ...);
connection.Open();
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
myCommand.Parameters["@Name"] = dataGridView1.Rows[i].Cells[0].Value.ToString();
myCommand.Parameters["@CostCenter"] = ...
...
myCommand.ExecuteNonQuery();
}
connection.Close();
DO NOT STORE DATES AS STRINGS IN THE DATABASE! Store them as the appropriate DateTime type.
|
|
|
|
|
SortedSet implements:
[System.Serializable]
public class SortedSet<T> : System.Collections.Generic.ICollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.ISet<T>, System.Collections.ICollection, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable There are numerous examples of using ElementAt on SortedSets on the web, like this [^], however, I find using it on a SortedSet<KeyValuePair<string, string>>
if (SortedNames != null)
{
for (int i = 0; i < SortedNames.Count; i++)
{
KeyValuePair<string, string> item = SortedNames.ElementAt[i];
Console.WriteLine(item);
}
}
creates a compile error: "CS0021 Cannot apply indexing with [] to an expression of type 'method group" ... I can't locate any matching error report for this and SortedSet.
fyi: I am using a custom IComparer<KeyValuePair<string, string>> for sorting, but, that's working as expected.
Hypothesis: something about using KeyValuePair results in this error.
Ideas ?
thanks, Bill
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
modified 23-Nov-20 1:47am.
|
|
|
|
|
Hey Bill!
For using KeyValuePair in SortedSet , you need to define IComparable for it. Until it's not there, SortedSet would not be able to work on the datatype (as inherently it is supposed to sort)
To see what I say, comment your ElementAt line and run the code. You will get a runtime error as "At least one object must implement IComparable."
UPDATE: Below sample works fine with ElementAt . Where is the gap?
Once we have a defined sorted data, we can access with ElementAt . I put up a quick example:
class SortedSetDemo
{
static void Main(string[] args)
{
var words = new string[]
{"the", "quick", "brown", "fox", "jumps",
"over", "the", "lazy", "dog"};
var wordSet2 = new SortedSet<KeyValuePair<int, string>>(new KVPKeyComparer<int, string>());
int x = 0;
foreach (string word in words)
{
x++;
wordSet2.Add(new KeyValuePair<int, string>(x, word));
}
Console.WriteLine("Set items in sorted order:");
for (int j = 0; j < wordSet2.Count; j++)
{
var item = wordSet2.ElementAt(j);
Console.WriteLine(item);
}
}
public class KVPKeyComparer<TKey, TValue> : IComparer<KeyValuePair<TKey, TValue>> where TKey : IComparable
{
public int Compare(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y)
{
if(x.Key == null)
{
if(y.Key == null)
return 0;
return -1;
}
if(y.Key == null)
return 1;
return x.Key.CompareTo(y.Key);
}
}
}
Outputs:
[1, the]
[2, quick]
[3, brown]
[4, fox]
[5, jumps]
[6, over]
[7, the]
[8, lazy]
[9, dog]
modified 23-Nov-20 4:44am.
|
|
|
|
|
Hi Sandeep,
Did you not see my statement: Quote: fyi: I am using a custom IComparer<keyvaluepair<string, string="">> for sorting, but, that's working as expected.
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|