VB.NET Pass label reference to thread in class - vb.net

hopefully you can either validate my assumption or point me in the right direction.
I'm working on a small GUI to monitor a variable DC power supply. The equipment communicates via a COM port. To do this I have created a Class to handle communicating with the PSU. I would like to implement a method in which the calling form (class) can pass 2 Label references to my PSU class which it can periodically update with voltage and current.
I have already worked out how to update a Label's text from outside the main thread (with Invoke), and I have worked out how to start a second thread running a method with no parameters. From my reading, I can only pass a single parameter to a parameterized thread start.
My current approach is to create a Collection and have the items be those two labels which I mean to pass. The method to create and start the thread accepts (what I think are) pointers to the two labels with the following:
Public Sub monitor(ByRef vLbl As Label, ByRef aLbl As Label)
Inside that sub (after some error checks and other tasks) I create a new Collection and add the two label references:
Dim coll As Collection = New Collection()
coll.Add(vLbl)
coll.Add(aLbl)
Which I then pass coll in the thread.Start call.
In the sub actually running on the other thread, I start it by breaking out the two labels:
Dim _vLbl As Label = coll(0)
Dim _aLbl As Label = coll(1)
Is this a sound approach to the problem? I realize that I could simplify some of this by eliminating the class approach and taking more of a procedural one, but I'm trying to develop my PSU class reference to be used by some other software tools as a library eventually. Please forgive if I have messed up the terminology, I haven't been doing this for long and am trying to teach myself how all of this works.
Thanks in advance.
Edit: Grammar Fail

For what it's worth, this isn't how I'd do it, as it violates separation of concerns. The code that knows how to read the PSU shouldn't need to know what a label is or how to update it. In the future, you might want to use something other than a label, or may wish to store the numbers in a database as you go, or you might want to use a globalized approach to formatting the number (for example). If you were ever to make those changes, you shouldn't have to touch the PSU code.
Instead, I would create an object, say, PSUMonitor, which does the monitoring. The PSUMonitor would raise an event with a custom EventArgs capable of carrying the data you wish to track.
Then, your UI form would subscribe to those events, read the numbers, and then format the information to put them on a label, two labels, a graph, a table, aor whatever else you want.

Related

Allow end user to create custom properties for a class. Make those properties visible to DGV

Good day.
Not sure how to word this but please stay with me.
I have several instances of several classes with various properties of various types.
My users (very small business that I work for) would like to perform custom calculations on those variables and display the results in a new DGV column.
For instance
DGV1 uses list(of Myclass) as it's datasource. The columns are automatically added instead of predefined.
One user thinks up a property they would like to always see on dgv1.
He decides that this new property should be the result of
(Myclass.property1 - Myclass.property2)
Iv'e never done this sort of thing and have no clue where to start. I do know that I can't possibly hard code every possible combination of properties. Also, there's know way for the users foresee every combination that they'll need.
It basically needs to be as flexible as excel.
I have a logictree style custom filter builder for queering against properties of theses objects. Some of the users also want to be able to use these custom properties as nodes in the filter.
I'm not even sure if there's a way to add a property to a class at run time and in such a manner that it behaves as properties which are hard coded.
I'd be grateful for your thought and advice on this matter. Also, If I'm unclear on anything then I apologize. Please let me know if I need to clarify something.
Thank you, in advance.
*Edit#
I have discovered Typebuiler and am reading up on it.
There is no real way to add properties to a class on runtime. Once a class is created it's basically set in stone.
You could however have a Dictionary(Of String, Object) to hold the name and value of "properties" in your class. Make all properties like this and you can sort of simulate addable and removable properties. This however is limited to the object.
If you also want your customers to be able to perform calculations, you will have to write a script engine or use one.
I suggest to use a JavaScript engine. With JavaScript you can add properties whenever you want and you have JavaScript as a complete scripting language (JS is not only limited to the web).
I can suggest NiL.JS (https://github.com/nilproject/NiL.JS) as an engine. It is fast and you can easily convert objects back and forth from JS to .Net.
Here is how to use it:
Dim o As New YourCustomObject() ' Your object (e.g. has a property x (double))
o.x = 5.0
Dim c As New Context() ' Create a new JS environment
c.DefineVariable("o").Assign(JSValue.Marshal(o)) ' Transfer the variable
c.Eval("o.x = 6.0;") ' Change the value in JS and it will change in .Net
MsgBox(o.x) ' 6.0
It's a little more difficult to retrieve properties added in JS, but it is possible. I suggest looking at the examples at the GitHub page.
I don't know about the licensing of Nil.JS but there are similar engine out there.

Best Practice for subroutines/functions arguments

Was having a nightmare trying to come up with a title to resume my question.
Anyway, my question is really simple, is it better to do this:
Private TxtbxUserName As New TextBox With {.Text= "XXXX"}
Private Sub DoSomething(ByVal TextBoxText as string)
Dim Text as String = TextBoxText
End Sub
or to do this?:
Private TxtbxUserName As New TextBox With {.Text = "XXXX"}
Private Sub DoSomething()
Dim Text as String = TxtbxUserName.text
End Sub
And what are the specific advantages of each method?
It's hard to say, with such a simplified example, since both options can be preferable, depending on the situation. Generally speaking, though, taking the value as an argument (as in your first example) is preferable to getting the value from the control directly. There are many reasons why, but here are a few that come to mind:
Reusability - You can call the method from anywhere, even if you get the value from a different control, a file, a message, or anywhere else.
Readability - It is easier to follow what the code is doing and why
Testability - It is easier to test the code because you can pass different values into it and test the results without having to touch the UI
As a general rule, you should get the values from the controls as quickly as possible, usually immediately in the control's events, and then pass the values as parameters into the various business methods. If the controls need to be updated with any results, the controls should be set as late as possible. The business methods should return the values rather than setting the values of controls directly.
However, that being said, if you have a method which is entirely, or at least almost entirely, dealing with the UI, it may make sense for it to work with the controls directly. For instance if you are populating a tree control with data from an XML file which defines the node-layout for your UI, it may make sense to access the tree control directly in the method. It wouldn't necessarily make sense to load the data into some sort of tree data-structure just to turn around and read the tree data-structure to populate the tree. It depends. Basically, if it's a UI helper method--something to make it easier to work with a particular control--then it makes sense, sometimes, to have it work with the control directly. Otherwise, if it's a standard business logic method, you'll want to keep UI-related stuff out of it as much as possible.
As well as what Steven Doggart wrote, it could make more sense to use a function:
Private Function DoSomething(ByVal target As Control) As String
Return target.Text
End Function
as then you are not creating side-effects - in the case of your examples the side effect is altering a variable which is outside the scope of your method.

vb.net - what to name my refresh (data) method in a usercontrol

I run across this problem every time I create a UserControl which displays some data and I need a method that refreshes the data. I like to use simple common names for everything, and follow the principal of least astonishment and have names that are intuitive for others (or me 6 months from now) to understand.
The obvious name for my method would be Refresh, but that's already used by the base class.
I don't want to Override it, because I don't need to refresh my data every time the base class calls this method. Data refresh and screen refresh are just different functions and I don't think they should be mingled.
I don't want to Shadow it either, because I don't want to interfere with it's functioning.
Something I have not learned yet, which to me is interesting, is that if I Overloads it, MyBase.Refresh() takes me to the Object Browser, and Me.Refresh() takes me to my method.
Public Overloads Sub Refresh()
'Code to refresh data
End Sub
Me.Refresh() shows up in the Object Browser under my class, and the Refresh belonging to Control shows up under UserControl. Interesting as I never noticed that before.
I'm not sure if this avoids a collision with the base class in all cases or not! I mean, what about late binding? Like I say, I'm not even sure how the compiler knows them apart, but I can see that it does.
It seems like a neat trick but it would astonish anyone using my control, right? Would that astonish you?
What name is the standard name for such a function?
Better yet, is there a list of vb.net method names that are industry standard for basic common operations?
Minutia:
To nit pick, technically, it's not always a Reload, because I'm not always re-loading all the data; maybe I'm just incrementally syncing it. Load connotes an initial load, not a refresh. Sync is more like it, but this is not the first place most people would look in intellisense for this method, I would think. The name itself should not be astonishing. Update is ambiguous; who is updating who, i.e., which direction is the update going? DataBind is technically incorrect if I'm not actually using data binding or a data source. And any name that I can think of that fits all these criteria may not be in common use - RefreshData, for example. Not to mention, finally, that a one word name would be simpler.
Reload is not so bad. I think a name reload doesn't have to worry about how it's reloaded (sync vs full load).

How can I pass variables from form to form?

When working with a collection of forms that the user must step through, is it better to pass the data foward when creating a new instance of that form, or is it better to call a function from the previous form? I have some code written that calls the previous routine, and it looks ugly, and I can't quite think of a reason why it was done that way. The only reason I could come up with was if the data was large, and there was a good chance that the user wouldn't use the data except in a special case.
If you put all your shared data in a class, and then pass a reference to an instance of that class to the constructor on each form, then it doesn't matter how large the data is as it is only a reference being passed each time.
This has advantage that your forms are not tied to each other.
That's a subjective question for the most part. I personally took a route that seemed easier to maintain for people who will have to deal with my code later. I would instantiate the form, load the public properties with whatever I was trying to pass and then make the form visible. That way, anyone editing the 'new' form knew that all the data was pre-loaded. Anyone editing the 'old' form knew where to load any new properties.
If the new form will need the data immediately then it is probably better to pass it in the constructor of this form.
Use a new form and you can pass the values from form on other using server.transfer
You can read about Server.Transfer here : http://www.dotnet-guide.com/servertransfer.html
You could have a global data variable that stores all your data. Each form could access it independently. If you had a multi-threaded implemenatation, you could simply add thread-safety on the accessors of the global data variable.
The two main options i normally use are to either store the information in a database such as SQLServer or MS-Access if there is alot of information that many forms will use, or if the information is only going to be used in the next form I would pass the information to that form and then store it as appropriate. i.e. if it create a data table for it to use as a source, store the info in a hiddenfield, or even putting the information into the text boxes, labels, combo boxes etc. that they need to go into upon loading.
if you are talking about winforms (not webforms) then you should probably use a static class. Use a static member to hold onto the reference of the context object (or whatever you plan to share with other forms). All static member are guaranteed to be initialized before their first use.
A similar alternative would be to use the singleton design pattern to create a singleton class.
In effect these two solutions just make it possible to access a single reference globally, which is a power that can be over used at times so... be careful.

Selecting the Correct View for an Object Type

I've had this problem many times before, and I've never had a solution I felt good about.
Let's say I have a Transaction base class and two derived classes AdjustmentTransaction and IssueTransaction.
I have a list of transactions in the UI, and each transaction is of the concrete type AdjustmentTransaction or IssueTransaction.
When I select a transaction, and click an "Edit" button, I need to decide whether to show an AdjustmentTransactionEditorForm or an IssueTransactionEditorForm.
The question is how do I go about doing this in an OO fashion without having to use a switch statement on the type of the selected transaction? The switch statement works but feels kludgy. I feel like I should be able to somehow exploit the parallel inheritance hierarchy between Transactions and TransactionEditors.
I could have an EditorForm property on my Transaction, but that is a horrible mixing of my UI peanut butter with my Model chocolate.
Thanks in advance.
You need to map your "EditorForm" to a transaction at some point. You have a couple options:
A switch statement...like you, I think this stinks, and scales poorly.
An abstract "EditorForm" property in base Transaction class, this scales better, but has poor seperation of concerns.
A Type -> Form mapper in your frontend. This scales fairly well, and keeps good seperation.
In C#, I'd implement a Type -> Form mapper like this:
Dictionary <Type,Type> typeMapper = new Dictionary<Type,Type>();
typeMapper.Add(typeof(AdjustTransaction), typeof(AdjustTransactionForm));
// etc, in this example, I'm populating it by hand,
// in real life, I'd use a key/value pair mapping config file,
// and populate it at runtime.
then, when edit is clicked:
Type formToGet;
if (typeMapper.TryGetValue(CurrentTransaction.GetType(), out formToGet))
{
Form newForm = (Form)Activator.CreateInstance(formToGet);
}
You probably don't want to tie it to the inheritance tree--that will bind you up pretty good later when you get a slight requirements change.
The relationship should be specified somewhere in an external file. Something that describes the relationship:
Editing AdujustmentTransaction = AdjustmentTransactionEditorForm
Editing IssueTransaction = IssueTransactionEditorForm
With a little bit of parsing and some better language than I've used here, this file could become very generalized and reusable--you could reuse forms for different objects if required, or change which form is used to edit an object without too much effort.
(You might want users named "Joe" to use "JoeIssueTransactionEditorForm" instead, this could pretty easily be worked into your "language")
This is essentially Dependency Injection--You can probably use Spring to solve the problem in more general terms.
Do I miss something in the question? I just ask because the obvious OO answer would be: Polymorph
Just execute Transaction.editWindow() (or however you want to call it), and
overwrite the method in AdjustmentTransaction and IssueTrasaction with the required functionality. The call to element.editWindow() then opens the right dialog for you.
An alternative to the Dictionary/Config File approach would be
1) to define a interface for each of the transaction editors.
2) In your EXE or UI assembly have each of the forms register itself with the assembly that creates the individual transaction.
3) The class controlling the registration should be a singleton so you don't have multiple form instances floating around.
3) When a individual transaction is created it pulls out the correct form variable from the registration object and assigns it do an internal variable.
4) When the Edit method is called it just uses the Show method of the internal method to start the chain of calls that will result in the display of that transacton editor.
This eliminates the need for config files and dictionaries. It continues to separate the UI from the object. Plus you don't need any switch statement
The downside is having to write the interface for each every form in addition to the form itself.
If you have a great deal of different types of editors (dozens) then in that case I recommend that you use the Command Pattern
You have a master command that contains the dictonary recommend by Jonathan. That commands in turns will use that dictornary to execute one of a number of other command that calls the correct form with the correct object. The forms continue to be separate from the object themselves. The forms reside in the Command assembly. In addition you don't have to update the EXE to add another editor only the Command assembly. Finally by putting things inside of Command you can implement Undo/Redo a lot easier. (Implement a Unexecute as well as a Execute)