|
OriginalGriff wrote: MDN patients
I didn't realise users of the Mozilla Developer Network[^] were classed as "patients".
(I suspect you meant "MND", or "get me another coffee".)
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
It's the last one ...
"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!
|
|
|
|
|
Message Removed
modified 6-Jan-22 3:14am.
|
|
|
|
|
Hello,
I have a simple question I think, but do not seem to find an answer easily
I have a lisbox and a gridview. Both are connected to a database through the design editor.
visualisation works, but now I want to show only the items in the gridview which are connected to a chosen item in the listbox.
I already set the listbox to visualize a name and the value member to have the "primary key".
Now I want to show only the items in the gridview who are connected to this primary key.
Inside the design editor I can add a query like this :
SELECT pkID, ProductieVolgorde, Stuknr, Rolnr, AantalMeters, DatumTijd, Status, fkPO
FROM dbo.tblDoek1
WHERE fkPO = @What do I place here?
how do I link the chosen value member of the listbox to this fkPO in the query?
Is there somewhere a simple tutorial on how to link a database fully inside the Design editor?
thanks in advance
|
|
|
|
|
You use the SelectedIndexChanged event of the ListBox, in conjunction with the SelectedItem (as "Type") property, to sync the ListBox with the GridView (filter).
ListBox.SelectedIndexChanged Event (System.Windows.Forms) | Microsoft Docs
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
Hi, there. So you have a listbox with, for example, country names, and you want to display in the datagridview a list only of the cities of the country selected in the listbox. You actually don't need a whole new query for this. This is called a master-detail relationship (so you can google for that), or more precisely, a one-to-many relationship.
In the designer, you can set up a relation between the two tables. Then you use the table adapter to load the tables as usual. But you set the data source of the datagridview to the same binding source of the listbox, with the data member set to the relation. So, the master binding source points to the data table in the data set. Then the detail binding source points to the relation in the master binding source.
On the form, once you set the bindings this way, it's all automatic. When the selected item in the list box changes, the datagridview automatically updates.
A different method is this. Set the master binding source to its master table, and the detail binding source to its detail table. Then, when the selected value in the listbox changes, intercept the event and set a filter on the detail binding source (which is bound to the datagridview).
The first method is mostly done in designer, and the second is done mostly in code. You could create a query for this purpose, but these two methods would generally be more efficient. I hope this helps!
modified 7-Jan-22 18:08pm.
|
|
|
|
|
Hello RobertSF,
that was the asnwer I was looking for thanx!
Will any changes in the gridview be adapted in the database too this way?
edit : I spoke too early when I change the selection in my listbox the application hangs
modified 12-Jan-22 5:53am.
|
|
|
|
|
If the grid is edited, yes, you can propagate the changes to the database. It won't happen automatically. You'll first have to call EndEdit on the binding source and possibly first on the grid, and then use either a table adapter update method or the dataset update method.
It's pretty rare for applications to hang, in my experience. They more often crash with exceptions, though they can also get stuck in infinite loops. Try working with the debugger and going line by line.
Or google for "master detail two datagridview" and try it with two grids instead of listbox and a grid. I don't think I can post link, but the full title of the Microsoft document is "Walkthrough: Creating a Master/Detail Form Using Two Windows Forms DataGridView Controls"
|
|
|
|
|
Maybe this will help. I created an Access database with two tables.
Table: Countries
-string: CountryName
Table: Cities
-string: CountryName
-string: CityName
No relationships created between the two tables. Entered three countries (USA, Canada, Mexico), and three cities in each country.
In Visual Studio, created a new dataset with the two tables from the database. Here, I did create a relationship, linking the Cities table to the Countries table by the CountryName column. The relationship, which exists only in Visual Studio, is called Countries_Cities.
Then I created a form and dropped a ListBox into the form. Setting the DataSource to the Countries table (you must drill down in Designer) automatically creates the countriesBindingSource. Then I set the DisplayMember to CountryName. Here are the binding setting for the ListBox.
this.listBox1.DataSource = this.countriesBindingSource;
this.listBox1.DisplayMember = "CountryName";
Then I dropped a DataGridView into the form. When I clicked the button to select the Data Source, my choices were countriesBindingSource and Other Data Sources. Drill down into countriesBindingSource and select the Countries_Cities relationship. This will automatically create the countriesCitiesBindingSource and will auto-populate the DataGridView with two columns, CountryName and CityName. You can delete the CountryName column. Here are the binding values for the DataGridView.
this.dataGridView1.DataSource = this.countriesCitiesBindingSource;
This is all designer code, so you need not code anything so far. Now run the application. The form should appear, showing the countries in the List Box, but only the cities for the selected country in the DataGridView.
Click on the other countries in the ListBox, and the DataGridView should automatically show only the cities for the selected country. I hope this helps. This stuff can be pretty crazy-making because there are few practical examples to follow.
|
|
|
|
|
This is a program I have been tinkering with for my daughter to help her budget her finances. I understand that there are programs out there, but I wanted something to do and decided to play around with do this.
I am working on the income section, which has income coming in either weekly, semi monthly, bimonthly, monthly or yearly. What I am showing is the weekly section and I am curious as to whether there is a better method, which there usually is to what I am attempting to accomplish.
The "ds.Tables[0].Rows[i][0].ToString()" brings in the test verbiage for whether its weekly, monthly, whatever.
The "f" variable in the for loop is a numerical response provided by the user as to how far out they which to forecast their budget. 4 weeks, 6 weeks, 8 weeks and so forth.
If there is more detail needed, please let me know.
if (ds.Tables[0].Rows[i][0].ToString() == "Weekly (52)")
{
var date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
for (int x = 1; x < 7; x++)
{
if (ds.Tables[0].Rows[i][1].ToString() != date.ToString("ddd"))
{
DateTime newdate = date.AddDays(1);
date = newdate;
}
else
{
for (int n = 0; n <= ((4*f)-1); n++)
{
list.Add(date);
DateTime newdate = date.AddDays(7);
date = newdate;
}
break;
}
}
}
Thank you,
Richard
Disable Vet
Grandfather
Pain in the @ss
|
|
|
|
|
You refer to your daughter as "the user"? Unless she's a CEO, she could probably get by with Excel; they even have "budget templates".
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
I'd start with something like this:
private static DateTime NextWeekDay(DateTime date, string expectedDayOfWeek, DateTimeFormatInfo dateFormat)
{
int expectedDayIndex = Array.IndexOf(dateFormat.AbbreviatedDayNames, expectedDayOfWeek);
if (expectedDayIndex != -1)
{
int dayOfWeek = (int)date.DayOfWeek;
if (dayOfWeek != expectedDayIndex)
{
int daysToAdd = expectedDayIndex - dayOfWeek;
if (daysToAdd < 0) daysToAdd += 7;
date = date.AddDays(daysToAdd);
}
}
return date;
}
DateTime today = DateTime.Today;
DataTable dt = ds.Tables[0];
DateTimeFormatInfo dateFormat = DateTimeFormatInfo.GetInstance(CultureInfo.CurrentCulture);
foreach (DataRow row in dt.Rows)
{
string budgetType = row[0].ToString();
switch (budgetType)
{
...
case "Weekly (52)":
{
DateTime date = today.AddDays(1 - today.Day);
string expectedDayOfWeek = row[1].ToString();
date = NextWeekDay(date, expectedDayOfWeek, dateFormat);
int max = (4 * f);
for (int n = 0; n < max; n++)
{
list.Add(date);
date = date.AddDays(7);
}
break;
}
...
}
} Further optimisation may be possible depending on what the rest of the code looks like.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
If the code works and it is clear to you, then don't go changing it just for the sake of changing it. I often hear people talking about "improving" code, but they are vague on what improvement actually means in this case. Sure, there are some minor optimisations that jump out but whether or not they are worth putting in is debatable.
|
|
|
|
|
Hello Guys,
I have a CSV file which looks something like this :
Entry Price, Quantity, SL Level, TP Level, Side
nothing, nothing, nothing, nothing, nothing
As you can see, using the code below, I try to make sure if I have the file already, otherwise I create one with the same content above :
if (!File.Exists(path))
{
sw = File.AppendText(path);
if (writeHeaders) {
sw.WriteLine("Entry Price, " + "Quantity, " + "SL Level, " + "TP Level, " + "Side");
writeHeaders = false;
}
sw.WriteLine("nothing" + "," + "nothing" + "," + "nothing" + "," + "nothing" + "," + "nothing");
sw.Close();
}
but the if a position is taking place, I want to replace "nothing" with real values, depends on each column :
if (File.Exists(path) && PositionAccount.Quantity > 0)
{
List<string> newLines = new List<string>();
string[] existingLines = File.ReadAllLines(path, encode);
foreach (string line in existingLines)
{
string[] columns = line.Split(new char[] {','});
string EntryPrice = columns[0];
string Qtty = columns[1];
string SSLevel = columns[2];
string TTPLevel = columns[3];
string PSide = columns[4];
EntryPrice = EntryPrice.Replace("nothing", PositionAccount.AveragePrice.ToString());
Qtty = Qtty.Replace("nothing", QtyMini.ToString());
SSLevel = SSLevel.Replace("nothing", LongSL.ToString());
TTPLevel = TTPLevel.Replace("nothing", LongTP.ToString());
PSide = PSide.Replace("nothing", "Long");
columns[0] = EntryPrice;
columns[1] = Qtty;
columns[2] = SSLevel;
columns[3] = TTPLevel;
columns[4] = PSide;
string newLine = string.Join(",", columns);
newLines.Add(newLine);
}
File.WriteAllLines(path, newLines);
}
both above codes are working perfectly, and doing what they are supposed to do, EXCEPT THAT, when I try to READ the csv file from another strategy, it shows an Errors Message of "Error Msg : the process cannot access the file used by another process" and it disables everything.
I really tried all possible ways that I came across in all forums to fix this problem, but I was not able to do it, I think that the file is not closed from the first opening this is why it shows this message, so I tried
using () , I tried FileSharing, File Access, I tried FileStream, I tried StreamReader, but in some of them I was not able to readalllines and writealllines, as well I was not able to read only line[1] for example, and modify it and replace it.
using (mystream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
}
Can you plz tell me how to fix it ? Thank you
|
|
|
|
|
You're doing a "read all", then a "write all", both to the same "path".
"Simple" requires that you "write" to a different file than the one you're reading.
Other scenarios are more advanced.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
|
Thanks for bring this up; I wasn't aware they existed.
That's interesting: an immutable class with a value comparison.
That's basically a value type that can be inherited from, which is a big limitation - there are times when it would have been nice to inherit from int to add specific functionality without having to encapsulate it and manually build the comparison operators (since classes always default to a reference equality) - a record does a property-by-property value comparison for you, and is by default immutable. Nice.
Not sure what I'll use them for yet, but they are well worth remembering for future projects.
Good question!
"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!
|
|
|
|
|
You're welcome!
Sing the praise when you do!
|
|
|
|
|
I might be missing the benefit because records, I suspect, target things like data manipulation / EntityFramework, which is as far as possible from what I am doing now, both at work and home....
|
|
|
|
|
I guess they are quite handy to quickly create non trivial dictionary key...
for example:
public static WeakDictionary<TKey, TValue> Get<TKey, TValue>()
where TValue : class
where TKey : notnull
{
var k = new Key(typeof(TKey), typeof(TValue));
if (!caches.TryGetValue(k, out var result))
{
lock (caches)
{
if (!caches.TryGetValue(k, out result))
{
result = new WeakDictionary<TKey, TValue>();
caches[k] = result;
}
}
}
return (WeakDictionary<TKey, TValue>)result;
}
record class Key(Type key, Type value);
readonly static ConcurrentDictionary<Key, IWeakCache> caches = new();
|
|
|
|
|
trying to imagine what goes on in this code: smoke started coming out of my ears
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
Super Lloyd wrote: Though I wonder why it's available only to records.
Not the case since C# 10:
Beginning with C# 10, a left-hand operand of a with expression can also be of a structure type or an anonymous type.
Still not available for regular classes though.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
|
You might enjoy this discussion on Reddit: What is the point of records [^].
imho, Records major potential benefit is: immutability.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
Good find Bill, thanks!
|
|
|
|
|