Question about adding controls to a winform - winforms

In .NET Winforms, if I have some code which does something such as execute a stored proc against a SQL Server but I do not know how many parameters there are, can I add more controls to the form with the controls appearing straight away?
Thanks

Not sure exactly what you're asking here, but you can always add controls to a form dynamically. So, for example, if your code can determine that a stored procedure requires three string parameters, you could dynamically add three text boxes (plus three labels) to your form to allow users to enter values for these three parameters.

Related

SSRS : Passing parameters to a subreport

I have a report containing 3 different subreports (each accepting a different set of parameters), and only displaying one of them depending on the value of a parameter.
When I choose to display any one of them, it gives me the following error:
Error: Subreport could not be shown
I need to have this visibility parameter let me decide which subreport I wanna see, then have the ability to pass the right parameters to that chosen subreport. Is there any way of doing this ?
Here are some screenshots:
https://imgur.com/a/n8bKny8
OK, I understand how you have structured the report now. I think the approach is a little wrong. It's like you are mixing two appraoches.
If you are trying to make this like a "Wizard", step-by-step approach, then you could simply change your main report to have 3 text boxes, one for each report, with a "Go to Report" action set. This will simply open the 'subreport' (it won't technically be a sub-report now) and then you can select parameters as normal. Optionally, format the textbox and make it look more like a button.
The other approach if you want to do this all in a single step would be to change the main report have all the parameters that are required across all subreports and allow the user to set them there (in the main report). These parameters can then be passed to the subreport via the subreport properties (parameters tab).
It really depends on the user experience you want to achieve but the simplest option would be the first option.
If this does not help, I'll try to post an example later tonight.

What control should I use for getting the following rows in ssrs?

I am to design a report which will be having given rows, I have tried with Tablex and Matrix, but I am facing issue with grouping.
Is there any other control or any custom control or any way of customizing Table
which I can use to design the following formatted rows in report.
Any link with demo, sample or POC would be great help.
Kind hard to tell what you're going for from your picture/description, but I'm guessing you may want to use a List object. You can put your group at the list object level, and then add text boxes, tables, images or whatever you need inside the list. You'll get a set of whatever is inside the list for each group, using the data from that group. Take a look at the sample/description here, which looks similar to what you're trying to do: here

How to quickly populate a combobox with database data (VCL)

I have read all sorts of documents across the web about what should be a farly common and painless implementation. Since I have found no consistent and slick reply (even the Embarcadero website describes some properties wrong!) I am going to post a "short" howto.
Typical, frequent use case: the developer just wants to painlessy show a couple of database-extracted information in a combo box (i.e. a language selection), get the user's choice out of it and that's it.
Requirements:
Delphi, more or less any version. VCL is covered.
A database table. Let's assume a simple table with an id and value fields.
A DataSet (including queries and ClientDataSets).
A DataSource linked to the DataSet.
A TDBLookupComboBox linked to the DataSource that shall show a list of values and "return" the currently selected id.
Firstly, we decide whether the sort order is the one we want or not and if all the items in that table must be shown. Most often, a simple ORDER BY clause or a DataSet index will be enough. In case it's not, we may add a sort_order field and fill it with integers representing our custom sort order. In case we want to show just some items, we add a visible or enabled field and use it in our SQL. Example:
SELECT id, value
FROM my_database_table
WHERE visible = 1
ORDER BY sort_order
I have defined visible as INTEGER and checking it against 1 and not TRUE because many databases (including the most used SQLite) have little support for booleans.
Then an optional but surprisingly often nice idea: temporarily add a TDBGrid on the form, link it to the same TDataSource of the TLookupComboBox and check that you actually see the wanted data populate it. In fact it's easy to typo something in a query (assuming you are using a SQL DataSet) and get no data and then you are left wondering why the TDBLookupComboBox won't fill in.
Once seen the data correctly show up, remove the grid.
Another sensible idea is to use ClientDataSets for these kinds of implementations: due to how they work, they will "cache" the few rows contained in your look ups at program startup and then no further database access (and slowdown and traffic) will be required.
Now open the TDBLookupComboBox properties and fill in only the following ones:
ListSource (and not DataSource): set it to the TDataSource connected to the DataSet you want to show values of.
ListField: set it to the field name that you want the user to see. In our demo's case it'd be the value field.
KeyField: set it to the field name whose value you want the program to return you. In our demo it'd be the id field.
Don't forget to check the TabOrder property, there are still people who love navigating through the controls by pressing the TAB key and nothing is more annoying than seeing the selection hopping around randomly as your ComboBox was placed last on the form despite graphically showing second!
If all you need is to show a form and read the TDBLookupComboBox selected value when the user presses a button, you are pretty much sorted.
All you'll have to do in the button's OnClick event handler will be to read the combo box value with this code:
SelectedId := MyCombo.KeyValue;
Where SelectedId is any variable where to store the returned value and MyCombo of course is the name of your TDBLookupComboBox. Notice how KeyValue will not contain the text the user sees onscreen but the value of the id field we specified in KeyField. So, if our user selected database row was:
id= 5
value= 'MyText'
MyCombo.KeyValue shall contain 5.
But what if you need to dynamically update stuff on the form, depending un the combo box user selection? There's no OnChange event available for our TDBLookupComboBox! Therefore, if you need to dynamically update stuff around basing on the combo box choices, you apparently cannot. You may try the various "OnExit" etc. events but all of them have serious drawbacks or side effects.
One possible solution is to create a new component inheriting from TDBLookupComboBox whose only task is to make public the hidden OnChange event. But that's overkill, isn't it?
There's another way: go to the DataSet your TDBLookupComboBox is tied to (through a DataSource). Open its events and double click on its OnAfterScroll event.
In there you may simulate an OnChange event pretty well.
For the sake of demonstration, add one integer variable and a TEdit box to the form and call them: SelectedId and EditValue.
procedure TMyForm.MyDataSetAfterScroll(DataSet: TDataSet);
var
SelectedId : integer;
begin
SelectedId := MyDataSet.FieldByName('id').AsInteger;
EditValue.Text := MyDataSet.FieldByName('value').AsString;
end;
That's it: you may replace those two demo lines with your own procedure calls and whatever else you might need to dynamically update your form basing on the user's choices in your combo box.
A little warning: using the DataSet OnAfterScroll has one drawback as well: the event is called more often than you'd think. In example, it may be called when the dataset is opened but also be called more than once during records navigation. Therefore your code must deal with being called more frequently than needed.
At this point you might rub your hands and think your job is done!
Not at all! Just create a short demo application implementing all the above and you'll notice it lacks of an important finishing touch: when it starts, the combo box has an annoying "blank" default choice. That is, even if your database holds say 4 choices, the form with show an empty combo box selected value at first.
How to make one of your choices automatically appear "pre-selected" in the combo box as you and your users expect to?
Simple!
Just assign a value to the KeyValue property we already described above.
That is, on the OnFormCreate or other suitable event, just hard-code a choice like in example:
MyCombo.KeyValue := DefaultId;
For example, by using the sample database row posted above, you'd write:
MyCombo.KeyValue := 5;
and the combo box will display: "MyText" as pre-selected option when the user opens its form.
Of course you may prefer more elegant and involved ways to set a default key than hard-coding its default value. In example you might want to show the first alphabetically ordered textual description contained in your database table or whatever other criterium. But the basic mechanic is the one shown above: obtain the key / id value in any manner you want and then assign it to the KeyValue property.
Thank your for reading this HowTo till the end!

How to dynamically populate a report?

Hopefully this is the last question I have about Access since I will be done working with it very soon.
I currently have a report that is generated from a form that is filled out when a "Run" button is pressed. A database primary key is searched for and the form is populated. When the user clicks a "Print" button, a printable report is generated, being populated by data from that form. All of that was easy.
Now, in the form, there is a single list box. That list box displays results for a transaction type depending on which transaction type is clicked. For example, clicking "Purchase" will yield all customers who have purchased something in the list box, and clicking "Sold" will yield all customers who have been sold something in the list box. There are many more transactions than those two, but that does not matter for the purpose of this question.
What I need to do is make the contents of that list box (which is populated by a query in VBA) for every transaction type appear on the printable report.
So for example, the report might look something like this:
Purchases:
John
Cindy
Alex
Sold:
Matt
Steven
John
Rob
Does anyone know a simple way to do this? I can vaguely think of how I might do this, but it is complex and I don't know the exact functions I would need to use. Basically I was thinking I would run the query that populates the list box, but then parse through each result in a while loop, and display it on the report.
Thank you in advance for any help!
A Report is a fairly static object in comparison to a Form. To dynamically change the data that is displayed in a report you would typically use the Where argument for OpenReport, usually on a button press and reading some value from a control on the currently active form:
DoCmd.OpenReport "rptName", acViewPreview, , "SomeField=" & frmName!ctlName
If the value on the form is a string then it needs to be surrounded with apostrophes:
DoCmd.OpenReport "rptName", acViewPreview, , "SomeField='" & frmName!ctlName & "'"
A report also has a Filter property that you might use, or you can programmatically set its RecordSource. The first option is the most common, and the easiest.
If the report has a listbox then you would typically modify its RowSource, using a query with a criteria that refers to a control on your form. But I would question why this is necessary, as the listbox would have no relation to the rest of the data in the report.
If you are talking about dynamically changing what appears on the report - moving and hiding controls, etc. - then this is a different question. You would need to first open the report in Design View. This is unusual and rarely necessary. Typically, you would create a separate report, perhaps copying the original report, and just use the button to decide which report to display. (There are Report Events that can be used to hide, or move, controls on the report - OnFormat, for example - that wouldn't require the report to be opened in Design View, but I don't think this is what you are looking for.)
Assuming that the report will be created using the recordset that was used to create the form, you could join the recordset that populates the listbox to the recordset that populates the rest of the form. If you, say, LEFT JOIN the recordset for the list box to the recordset for the form on the transaction type, the resulting recordset should have every thing you need to create the report required.
If the report needs to chabnge its format based on the transaction type, try using the OnOpen and OnClose Events for the report and the OnFormat Event for the Detail sections. I have some experience with reports like that. If you need more help with the events, add comments with some specific detail and I can probably make useful suggestions.

WinForms - How do I create a table using a custom control for each row?

I want to create a table representing data I have, but I want each row to have a custom display. I have developed a little custom control that represents a row and has a few items in it (text box, check box, progress bar), however how do I now in the main form create multiple instances of this for the data I have?
e.g. is there a winforms control I can use to do this? or do I have to take a panel or something and programmatically do it?
I do need to somehow take responses back. So if someone clicks on the button in the 4th row say then I'll need to be able to tell which row it was from.
As an aside would then be a way to BIND the above mentioned visualization of my data to the data itself, say housed in an Array?
thanks
I see two options here:
You can use a DataRepeater. This control can be found in the Microsoft Visual Basic Powerpack. It allows you to place controls on a template which gets copied for each item in the databound collection.
You can create a custom control and manually place one instance of it for each item in a collection, re-creating databinding for the controls in it. This requires you to either expose the controls inside publicly or as properties of the user control.
However, above options are mostly useful for non-tabular data. If your layout is strictly tabular (i. e. rectangular cells in a grid) then you can create a custom DataGridViewCell which takes some time to understand but not too much code. Putting a progress bar into such a cell shouldn't prove too difficult.

Resources