|
I've worked a lot to try to get this working, but after several errors and trials, i've tried two things without error, but it doesn't work
here is my customer list load code
SQLiteParameter[] param = {};
customerList.Rows.Clear();
DataTable searchinfo = database.query_search("SELECT id, firstname, lastname FROM customers", param);
foreach (DataRow row in searchinfo.Rows)
{
customerList.Rows.Add(row[0].ToString(), row[1].ToString() + " " + row[2].ToString());
}
statusLabel.Text = searchinfo.Rows.Count.ToString() + " row(s) returned";
double clicking or clicking an 'edit' button successfully raises a child form
private void customerList_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
int index = e.RowIndex;
DataGridViewRow row = customerList.Rows[index];
String cid = row.Cells[0].Value.ToString();
editcustomer editdiag = new editcustomer();
editdiag.id = cid;
editdiag.ShowDialog();
}
I used a timer to filter results from a textbox that starts and stops based on textchanged
private void search_TextChanged(object sender, EventArgs e)
{
if(queryInterval.Enabled == false)
queryInterval.Start();
}
here is the 1000ms tick that stops itself after an idle match
public void queryInterval_Tick(object sender, EventArgs e)
{
if (lastQuery == search.Text)
{
queryInterval.Stop();
}
else
{
if (search.Text.Trim() != "" && search.Text.Length >= 3)
{
customerList.Rows.Clear();
SQLiteParameter[] param = {
new SQLiteParameter("@search", "%" + search.Text + "%")
};
DataTable searchinfo = database.query_search("SELECT id, firstname, lastname FROM customers WHERE firstname LIKE @search OR lastname LIKE @search", param);
foreach (DataRow row in searchinfo.Rows)
{
customerList.Rows.Add(row[0].ToString(), row[1].ToString() + " " + row[2].ToString());
}
statusLabel.Text = searchinfo.Rows.Count.ToString() + " row(s) returned";
}
else if (search.Text.Trim() == "")
{
SQLiteParameter[] param = { };
customerList.Rows.Clear();
DataTable searchinfo = database.query_search("SELECT id, firstname, lastname FROM customers", param);
foreach (DataRow row in searchinfo.Rows)
{
customerList.Rows.Add(row[0].ToString(), row[1].ToString() + " " + row[2].ToString());
}
statusLabel.Text = searchinfo.Rows.Count.ToString() + " row(s) returned";
}
else if (search.Text.Length < 3 && search.Text.Trim() != "")
{
}
lastQuery = search.Text;
}
}
i've tried directly running the load from the parent form on the child close
private void editcustomer_FormClosed(object sender, FormClosedEventArgs e)
{
customers custForm = new customers();
custForm.refresh(sender, e);
custForm.customers_Load(sender, e);
}
or blanked out the match text and started the timer
private void editcustomer_FormClosed(object sender, FormClosedEventArgs e)
{
customers custForm = new customers();
custForm.lastQuery = "";
custForm.queryInterval.Start();
}
I've done messageboxes in both the interval and the load and it does execute it, but the datagridview refuses to update. Is the parent form marked disabled till the form totally closes? Is there a better way to do this i'm not seeing?
yeah point is close the edit form and update the database and close the child form, have the parent update (name information updated, irrelevant if other data not seen is updated)
would iterating through the parent datagridview with the ID and upadting it manually work? I somehow doubt it if the other two is running, but not clearing the data and updating the new rows with the database data
thanks, sorry about the complexity of this
|
|
|
|
|
Your problem is to do with the way you display the child form: ShowDialog is a modal function: it does not return until the form it displays is closed. So the UI for Form1 is "busy" and doesn't get updated while the child form still exists.
Instead of ShowDialog, you can use Show - which allows both forms to continue working - but in any case you are going at this the wrong way:
1) Creating a new instance of the "parent" form and calling it's methods will not affect the existing one: it's a separate instance and does not share a DataGridView with any other. In order to directly update the parent, you would need to use the actual instance that opened the child, not a new one.
2) But the child form shouldn't even know the parent form exists, much less what type it is, or what methods it contains. Instead, the child should raise events that the parent handles and let teh parent do what it wants with the updates.
That probably sounds complicated, but it actually solves both your problems very neatly. Have a look here:
Transferring information between two forms, Part 2: Child to Parent[^]
It will show you how to do it properly.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
lol I actually ran across that page during my research. It sounds real complicated. a little blood just dropped from my nose
|
|
|
|
|
It's not difficult at all, not really - you've got the full code, and all it's doing is using the same event mechanism that everything else does, just you are creating and raising the event as well as handling it.
And creating an event is almost trivial, I do it so often I created a Visual Studio shortcut to to make it even simpler: A Simple Code Snippet to Add an Event[^]. Now I just type "evh" and press TAB and it fills out the event, just like "prop"+TAB creates a property.
Raising the event is just a case of calling a method!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I tried, and got errors, even downloaded the zip and it's pretty confusing. Keep in mind i've been doing c# for like, two weeks? Gotten fairly far using just google searches. Some specific things do elude me. Like your code. Still have a lot of specific stuff to figure out. like things like seeing {get; set;} at top and things like that I just don't understand. Mind you this program is going to be used by just me, nor will I be doing any business-level programming. I did some of that with PHP but never continued and never learned ajax/dhtml, which a lot of web sites require. My specialty is repair/support (which this program is for me to keep track of that)
aaaanyways, I found a solution, that I think I did put in my original post, but just using .show allowed my original form call to create a FormClosedEventHandler from the parent, which works. So now the child is doing nothing aware from the parent...sort of
|
|
|
|
|
Then you are trying to get way ahead of yourself - if you don't understand the basics like automatic properties:
MyType MyProperty { get; set; } Then you are missing huge chunks, and you need to wonder what else you have missed, and how it might have improved things and made your life - and code - easier.
How are you learning? A course, a book, YouTube (gawd forbid!), guesswork?
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
modified 23-Apr-20 6:16am.
|
|
|
|
|
google searches, guesswork. But as you can tell from my code i'm not doing TOO bad. I know some of the .net concepts, and did pretty well with vb.net (but I hate the syntax of vb.net)
did borland C++ in high school and a little in college to get me past the required single beginning programming class (my comp sci was focused for computer repair)
|
|
|
|
|
I guessed it might be that - it shows in your code.
Do yourself a favour - a pretty big favour - and get a book (Addison Wesley, Wrox, MS Press all do good ones, and there is also the Yellow Book[^] which is pretty good, and free).
A book has structure, and leads you through the topics - and at the very least makes you aware of stuff you might use even if you don't study it well. Random guesses and searching doesn't do that: if you don't know it exists or what it's called you can't find it out!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
wow $40. I'm not going to be making any money off my code so and it's a program just for me (and an easy one at that), i'll probably skip this, at least for the time being
|
|
|
|
|
Technical books aren't cheap because they take a lot of time and effort to write - and the author has to put a lot of work into learning how to teach and his subject before he even starts. (That's why most "how to code" videos on YouTube are such crap: the author doesn't know his subject well, he does kn ow how to teach, and he has no idea how to make a video.)
But the Yellow Book is free (there is a download on the page I linked to) and some of the others can be borrowed from public libraries or bought second hand. For those a lot less ethical, many of them can be stolen from the internet as EPUB or PDF files as well.
If we go back to cars, you are trying to learn to drive a F1 race by stealing Ford Fiestas and stamping on the throttle. If you don't know how the clutch works or even that "it's the pedal on the left" your gear changes are going to be noisy and clumsy forever; if you don't know which side the petrol filler cap is you're going to have fun at the fuel station; if you don't know that tires need a specific air pressure you're going to wear them out very quickly. And even if you guess all that eventually you still aren't going to beat Louis Hamilton!
With C# and the .NET framework, there is so much "stuff" that can make your life easier - if you use it right - that you won't even begin to guess it's in there! Linq, generics, interfaces, using blocks, try...finally, the Diagnostics class, overloading, databses, transactions, delegates, ... the list goes on a very, very long way.
The only way to find them is to learn them - and that means a book, or better a course, honestly.
Get the Yellow Book, and read it. It's a pretty good starting point.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
yeah I know about try...finally some generics and heh yeah overloading is beyond me. I've read about it and seen code samples, and delegates I have a blurry idea at best, because I have seen other code samples but yeah the base concept will have to be learned in a basic to advanced way a book does
again this program is easy, well...yeah I did have that big problem, but I overcame it. It's simple database and form stuff. I know a good amount about databases already with my time using php/mysql, but yeah I know there is a unifying sql subsystem in c# I haven't played with that has to do with sources, and binding, etc
|
|
|
|
|
The easiest way to do what you want is to create a static Globals class, and create the object in question in that class. At that point, it exists everywhere in the app, and you can read/modify the class' properties from any form.
It may not be "the best way", but it's probably the easiest way.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
Please help me
I need to calculate the balance columns in datagridview
For Example
DR CR Balance
100 0 100
200 0 200
0 100 100
|
|
|
|
|
Try adding the numbers together.
|
|
|
|
|
And what would you like us to do?
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
Responding to a QA question today, I was, finally, able to figure out the proper calling syntax for an extension method on Enum with a signature like this:
public static TEnum ToEnum<TEnum>(this Type tenum, string str, bool ignorecase = false)
where TEnum : struct, IConvertible{ ... } An example of the calling syntax:
WeekDays friday = typeof(WeekDays).ToEnum<WeekDays>("friday"); It kind of drove me crazy to figure this out, and the usual resources here, and on SO, didn't turn up any clues.
Assuming a week of days with temperature above 105F, plus adjusting to a locked-down city with high air-pollution, and a curfew, has not addled my brain more than old age ...
I wonder if it's possible I stumbled on something ... new. I seriously doubt that: more likely I came across something so weird nobody would want to do that.
Curious if you have seen this technique/syntax. I find it damn awkward.
Of course, I do expect @RichardDeeming to weigh-in and expose my ...
«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
|
|
|
|
|
Those type constraints will allow things other than Enum s though, which will cause an ArgumentException at runtime:
int x = typeof(int).ToEnum<int>("Friday");
If you're using a relatively recent compiler / language version (C# 7.3 or later), you can use an Enum type constraint if you want to be absolutely sure the type parameter is an Enum :
public static TEnum ToEnum<TEnum>(this Type tenum, string str, bool ignoreCase = false) where TEnum : struct, Enum { ... }
...
WeekDays friday = typeof(WeekDays).ToEnum<WeekDays>("friday");
int x = typeof(int).ToEnum<int>("Friday");
(This was supported in the CLR since generics were introduced in v2, but it was only added to C# in 2018.)
However, I'm not too keen on having to pass the enum type twice. It's not clear from the signature which type will be used - the generic type parameter, or the tenum argument.
For example, what is the expected output from the following (admittedly terrible) code?
enum A { Zero = 0, One = 1, Two = 2, Default = One }
enum B { Zero = 1, One = 2, Two = 4, Default = Two }
B x = typeof(A).ToEnum<B>("Default");
B y = typeof(A).ToEnum<B>("Two"); If it's using typeof(TEnum) and ignoring the tenum parameter, the answer will be Two and Two .
If it's using the tenum parameter, the answer will be Zero and One .
Enum constraints | C# Online Compiler | .NET Fiddle[^]
At the moment, I can only think of two alternatives:
public static class EnumHelper
{
public static TEnum ToEnum<TEnum>(string str, bool ignoreCase) where TEnum : struct, Enum { ... }
}
...
WeekDays friday = EnumHelper.ToEnum<WeekDays>("friday"); Or:
public static TEnum ToEnum<TEnum>(this TEnum ignored, string str, bool ignoreCase) where TEnum : struct, Enum { ... }
...
WeekDays friday = WeekDays.Monday.ToEnum("friday"); I have a slight preference for option 1.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
you da man Richard !
«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
|
|
|
|
|
@RichardDeeming ... Hi Richard, fyi: in the code I posted on QA [^] I do check to make sure the Type is 'Enum.:
public static TEnum ToEnum<TEnum>(this Type tenum, string str, bool ignorecase = false)
where TEnum : struct, IConvertible
{
if (! tenum.IsEnum)
throw new ArgumentException("TEnum must be an Enum type");
TEnum result;
if (Enum.TryParse<TEnum>(str, ignorecase, out result))
{
return result;
}
throw new ArgumentException($"{str} is not a valid string for conversion to {tenum.FullName}");
} Richard Deeming wrote: However, I'm not too keen on having to pass the enum type twice. It's not clear from the signature which type will be used - the generic type parameter, or the tenum argument. I'm uncomfortable with that syntax as well.
To make that more bomb-proof:
public static TEnum ToEnum<TEnum>(this Type tenum, string str, bool ignorecase = false)
where TEnum : struct, IConvertible
{
Type returntype = typeof(TEnum);
if (!returntype.IsEnum)
throw new ArgumentException("Return Type must be an Enum type");
if (!tenum.IsEnum)
throw new ArgumentException("Type parameter must be an Enum type");
if (tenum != returntype)
throw new ArgumentException("Type and Return type must be the same");
TEnum result;
if (Enum.TryParse<TEnum>(str, ignorecase, out result))
{
return result;
}
throw new ArgumentException($"{str} is not a valid string for conversion to {tenum.FullName}");
} Ideally, we'd have a way for these edge cases to not even compile, but, ideally it would not be 104F (feels like 110F) in Thailand right now, and my air-con would not be wimping out on me
«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 21-Apr-20 4:28am.
|
|
|
|
|
How about:
public static TEnum ToEnum<TEnum>(this Type tenum, string str, bool ignoreCase = false)
where TEnum : struct, Enum
{
#if DEBUG
if (tenum != typeof(TEnum))
throw new ArgumentException("Type {tenum.FullName} does not match return type {typeof(TEnum).FullName}");
#endif
if (Enum.TryParse<TEnum>(str, ignoreCase, out TEnum result))
{
return result;
}
throw new ArgumentException($"'{str}' is not a valid string for conversion to {typeof(TEnum).FullName}");
} The Enum constraint means you don't need to check whether TEnum is an Enum type; anything else would be a compiler error.
The tenum parameter isn't really used, so it probably makes sense to omit the comparison in a release build.
And if we're going to throw an exception if tenum is not the same as typeof(TEnum) , we don't really need to test whether tenum is an Enum type first.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
food for thought, thanks ! @RichardDeeming
today, i considered what it would mean to write a factory method to return a hard-coded converter ... what i came up with is rather monstrous but it works:
var econverter = WeekDays.Default.MakeConverter<WeekDays>();
WeekDays wkd = econverter("monday", false); can't say i see enduring value for such elaboration to achieve a limited result. i added a "Default" value to the Enum:
public static Func<string, bool, TEnum> MakeConverter<TEnum>(this Enum tenum)
where TEnum : struct, IConvertible
{
Type returntype = typeof(TEnum);
if (!returntype.IsEnum)
throw new ArgumentException("Return type must be an Enum type");
Type argtype = tenum.GetType();
if (! argtype.IsEnum)
throw new ArgumentException("Type parameter must be an Enum type");
if (argtype != returntype)
throw new ArgumentException("Type and Return type must be the same");
Func<string, bool, TEnum> xFunc = null;
try
{
xFunc = (string str, bool ignorecase) =>
{
TEnum result;
if (Enum.TryParse<TEnum>(str, ignorecase, out result))
{
return result;
}
throw new ArgumentException(
$"{str} is not a valid string for conversion to {typeof(TEnum).FullName}");
};
}
catch (Exception ex)
{
throw new TypeInitializationException(typeof(TEnum).FullName, ex.InnerException);
}
return xFunc;
}
«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
|
|
|
|
|
If you make the parameter TEnum , you won't need to check whether it's the same type as the type parameter, and you won't need to repeat the type when you call it.
public static Func<string, bool, TEnum> MakeConverter<TEnum>(this TEnum tenum) ...
var econverter = WeekDays.Default.MakeConverter(); I don't think you need to worry about getting an exception when you create the function - anything that's thrown then won't be recoverable anyway.
You can also let the compiler infer the parameter types for the returned Func<> .
public static Func<string, bool, TEnum> MakeConverter<TEnum>(this TEnum tenum)
where TEnum : struct, Enum
{
return (str, ignoreCase) =>
{
if (Enum.TryParse<TEnum>(str, ignoreCase, out var result)) return result;
throw new ArgumentException($"'{str}' is not a valid string for conversion to {typeof(TEnum).FullName}");
};
} With a throw expression[^], the converter function can come down to a single line:
return (str, ignoreCase) => Enum.TryParse<TEnum>(str, ignoreCase, out var result) ? result
: throw new ArgumentException($"'{str}' is not a valid string for conversion to {typeof(TEnum).FullName}"); You could even make the factory method an expression-bodied method, although I think that might be taking things a little too far:
public static Func<string, bool, TEnum> MakeConverter<TEnum>(this TEnum tenum) where TEnum : struct, Enum
=> (str, ignoreCase) => Enum.TryParse<TEnum>(str, ignoreCase, out var result) ? result
: throw new ArgumentException($"'{str}' is not a valid string for conversion to {typeof(TEnum).FullName}");
NB: If you want to maintain the optional parameter, you can't use the generic Func<> delegate; you'd need a custom delegate type:
public delegate TEnum EnumConverterDelegate<TEnum>(string str, bool ignoreCase = false) where TEnum : struct, Enum;
public static EnumConverterDelegate<TEnum> MakeConverter<TEnum>(this TEnum value) where TEnum : struct, Enum
=> (str, ignoreCase) => Enum.TryParse<TEnum>(str, ignoreCase, out var result) ? result
: throw new ArgumentException($"'{str}' is not a valid string for conversion to {typeof(TEnum).FullName}");
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
i think we're approaching apogee of our orbit around this planetoid
«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
|
|
|
|
|
This might be simpler
using System;
namespace EnumConvert
{
public enum MyEnum
{
None = 0,
First,
Second,
Third,
Last
}
public static class EnumExtensions
{
public static Tenum ToEnum<Tenum>(this Tenum theEnum, string str, bool ignoreCase = false)
where Tenum : struct, Enum
{
if (Enum.TryParse<Tenum>(str, ignoreCase, out Tenum result))
return result;
throw new ArgumentException($"{str} is not a valid string for conversion to {typeof(Tenum).FullName}");
}
}
class Program
{
static void Main(string[] args)
{
MyEnum myEnum = new MyEnum();
var none = myEnum.ToEnum("None");
Console.WriteLine($"'None' results in {none} with a value of {(int)none}");
var first = myEnum.ToEnum("First");
Console.WriteLine($"'First' results in {first} with a value of {(int)first}");
var last = myEnum.ToEnum("last", true);
Console.WriteLine($"'last' results in {last} with a value of {(int)last}");
try
{
last = myEnum.ToEnum("last", false);
Console.WriteLine($"'last' results in {last} with a value of {(int)last}");
}
catch
{
Console.WriteLine("Error trying to convert 'last' to MyEnum");
}
try
{
var random = myEnum.ToEnum("Random", true);
Console.WriteLine($"'Random' results in {random} with a value of {(int)random}");
}
catch
{
Console.WriteLine("Error trying to convert 'random' to MyEnum");
}
}
}
}
"Time flies like an arrow. Fruit flies like a banana."
modified 21-Apr-20 12:19pm.
|
|
|
|
|
thanks !
MyEnum myEnum = new MyEnum(); for me, using 'new on an enum to get a default value makes the code even more obscure. i view that language "feature" as a flaw, given the special structure of enums, and their special behaviors.
«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 21-Apr-20 14:56pm.
|
|
|
|
|