Delphi - Running code without showing form - delphi

What do you think about this programming practice:
- I need to execute one transaction at first form and after that to force some updates that are placed at another form (for each item that is shown at another form). I.e. it would be like show that form and click at some button. Because it is mandatory to execute these functionalities from second form, I thought to do it without showing second form. Is that good programming practice or you have some other recommendation?
Also, is it enough just to set property> Visible:=False before ShowModal for the second form or I need to do some other actions?

Well, it's unusual to have a form that you don't show. Normally you separate your business logic from the UI.
To answer your question, I don't think you need to call ShowModal at all. Just define a method on the form class and call that. Ultimately forms are just Delphi objects and you can use them as such. If you don't want to show them, don't call ShowModal or Show.

Second question first: Setting Visible := False is of no benefit because the point of all ShowXXX methods is to make the form visible. As David says, you could perform the actions without calling Show at all, provided of course your form doesn't rely on any OnActivate or OnShow code in order to do it's job properly.
As for whether this is a good idea, I say no!
As I've already pointed out there is a concern you have to watch out for. I.e. that currently (or even due to maintenance at some point in the future) your form relies on being visible to do its job properly.
Of course, you could work around that by letting the form flicker open, and be programatically closed. Clearly an aesthetically poor choice.
Not to mention the problems of getting it right. You'll end up writing a bunch of patch-work code to wrap the form so that it can do what you need to do, when you should rather do the following...
Correct Approach
Your form is currently doing at least 2 distinct things:
Visual UI control (call it A)
and "mandatory functionalities" (call it B)
It doesn't matter much whether B is doing validation rules, extra processing, or whatever.
B is a process that does not require user interaction.
Therefore, you need to:
Copy B into a non-UI location (either a simple unit with a custom object or a data module). Call it B*
Modify the form to call B* instead of using B.
Test that your form still behaves correctly.
Delete B
And now you can have your new form call B* instead.
The above approach will save you huge headaches in the future.

Related

How to bind from DataTemplate to Page's DataContext?

I've got a page where a DataTemplate is being used to bind to the model for that content, e.g.:
<DataTemplate x:DataType="models:MyDataType">
... content ...
</DataTemplate>
In that content, I need to be able to bind a Click event. I need that click event to exist in the view model that is set as the page's DataContext:
<Page.DataContext>
<vm:MyViewModel x:Name="ViewModel">
</Page.DataContext>
but I'm really struggling with getting it to compile. Every approach I try results in the compilation error "Object reference not set to an instance of an object".
I know I can't use x:Bind because that will bind to the DataTemplate's DataContext, so I've been trying to use Binding and, based on other SO answers I've read, it seems like the answer should be:
Click="{Binding DataContext.Button_Click, ElementName=Page}"
where Page is defined as the x:Name for the Page. I've tried removing DataContext. I've tried adding ViewModel.
What am I misunderstanding? Is it not possible to do what I want to do? I've tried using code-behind instead but I'm using Template 10 and that pushes almost everything onto the view model, which makes it harder for me to access things like the navigation service from code-behind.
tl;dr; use Messaging.
#justinXL is right, 'ElementName' can work. But is it best?
The problem you are trying to solve has already been solved with messaging. Most MVVM implementations include a messaging solution. Prism uses PubSubEvents; MVVM Light has its own messenger. There are others, too.
The idea is that an outside class, typically described as a message aggregator, is responsible for statelessly receiving and multicasting messages. This means you need to have a reference to the aggregator but not a reference to the sender. It’s beautiful.
For example
A common use case might be a mail client and how the data template of a message in the list would include a trash/delete button. When you click that button, what should be called? With messaging, you handle the button_press in the model and send/publish a message (one that passes the item).
The hosting view-model has subscribed to the aggregator and is listening for a specific message, the Delete message that we just sent. Upon receipt, it removes it from the list and begins the process to delete it from cache/database, or whatever – including prompting the user with “Are you sure?”
This means all your data binding in your data template is local, and does NOT extend outside its local scope. Why does this matter? Because if you use Element Binding to reach the hosting page, it means you cannot 1) move this template to a resource dictionary or 2) reuse this template.
There are two other reasons.
you cannot use compiled x:Bind to do this because it already limits use of this painful binding approach – this matters because a data template is typically in a list, and performance should always be prioritized, and
It adds considerable complexity.
Complexity?
I am a big fan of sophisticated solutions. I think they are rare and are the trademark of truly smart developers. I love looking at such code/solutions. Complex is not the same as sophisticated. When it comes to complexity, I am not a fan. Data binding is already difficult to wrap your head around; multi-sourcing your data binding across scope boundaries is pure complexity.
That’s what I think.
Your binding expression is correct, except it won't work with a Button_Click event handler. You will need an ICommand defined in your page's ViewModel.
Since you are using Template10, you should be able to create a DelegateCommand called ClickCommand like this
private DelegateCommand<MyDataType> _clickCommand;
public DelegateCommand<MyDataType> ClickCommand
{
get
{
_clickCommand = _clickCommand ?? new DelegateCommand<<MyDataType>>((model) =>
{
// put your logic here.
});
return _clickCommand;
}
}
And the binding will be updated to
<Button Command="{Binding DataContext.ClickCommand, ElementName=Page}" CommandParameter="{x:Bind}" />
Note I have also added a CommandParameter binding to the button as you might want to know which MyDataType instance is associated with the clicked button.

'cursor is in BOF position' error

On before delete of the table I have :
procedure TData_Module.MyTableBeforeDelete(DataSet: TDataSet);
begin
if MessageDlg('Are you sure you want to delete the record written by '+
QuotedStr(MyTable.FieldByName('written_by_who').AsString),mtConfirmation,[mbYes,mbNo],0) = mrYes then
MyTable.Delete;
end;
However, on trying I get the error :
...cursor is in BOF position
What goes ? Database is Accuracer.
edit : The entire code above :)
As I said in comments, it sounded from your q as if you are calling Delete within the dataset's BeforeDelete event. Don't do that, because the BeforeDelete event occurs while the dataset is already in the process of deleting the record. So you deleting it is pulling the rug out from under the dataset's built-in code.
So, if you want the user's confirmation, get it before calling Delete, not inside the BeforeDelete event. Btw, the standard TDBNavigator has a ConfirmDelete property associated with its integrated DeleteRecord button which will do exactly that, i.e. pop up a confirmation prompt to the user.
More generally, people frequently create problems for themselves by trying to perform actions within a dataset event which are inappropriate to the state the dataset is in when the event code is called. The TDataSet has a very carefully designed flow of logic to its operations, and t is rather too easy for the inexperienced on unwary programmer to subvert its logic by doing something in a TDataSet event that shouldn't be there: One example is calling Delete inside an event. Another, frequently encountered ,one is executing code which moves the dataset's cursor inside an event that's called as result of moving the cursor, like the AfterScroll event, f.i.
There's no easy rule to say what you should and shouldn't do inside a dataset event, but generally speaking, any action you take which attempts to change the dataset's State property (see TDataSetState in the OLH) should be your prime suspect when you find that something unexpected is happening.
I suppose another general rule, with exceptions that are usually clear from the descriptions of events in the OLH, is that dataset events should generally be used for reacting to the event by doing something to some other object, like updating a status panel, rather than doing something to the dataset. F.i. the AfterScroll event is very useful for reacting to changes when the dataset's cursor is moved. The exceptions are events like BeforePost which are intended to allow you the opportunity to do things (like validate changes to the dataset's fields).
Btw, you can call Abort from inside the BeforeDelete event and it will prevent the deletion. However, imo, it's cleaner and tidier to check whether a deletion should go ahead and plan and code for its consequences before going ahead rather than have to back out part way through. So, with respect, I disagree with the other answer. The time to decide whether to cross a bridge is before you start, not when you're already part way across it. Ymmv, of course.
The question is in the right place. To ask before the delete is wrong because it forces you to ask the question every time you call Delete. A more correct answer is to abort the delete here, in the OnBeforeDelete, if the user doesn't want to delete.

ASP.NET MVC - How to best build a form action that can respond in many ways?

I am in the process of writing a web app that includes a reporting form. This form contains a number of radio buttons that allow the user to specify the return data.
There are about 6 different return data 'formats', and each of those has two variations - html data or JSON data for rendering to a chart.
I have begun coding it up and already my form post action method feels wrong.
I basically have a check on the requested data format and return it as needed. Each return type requires its own partial view / json object so there is little room for reusing code.
It feels like each one should have its own action method. Having the form post to different locations based on a radio button choice also feels wrong though.
Switching on report type and then redirecting to the appropriate action in the controller also feels like its not quite right.
Am I approaching this in the wrong way? As it currently stands my controller action contains a lot of code and a lot of logic...
Hope my query makes sense.
Thanks
I don't think there is anything wrong with your approach. To maximize reuse you could:
include reusable templates inside your views
make sure the business/data layer code is the same everywhere (where possible)
I suppose the views you need to return actually are different for each combination of options so whatever approach you take, you are stuck with that.
I wouldn't opt for the client-side approach. You then have code on both the server and the client that has to be updated whenever you change anything. I would keep the code that receives a set of options and determines what to do with them in one place.
I know what you mean about it feeling like each format should be a separate action, but maybe a hybrid approach would make it feel better.
If you set the value of each radiobutton to the name of the action it relates to, you then, in your main POST action, have a parameter that you can use to call the appropriate action in one line of code. You don't have to fudge anything in Javascript, it's easily extensible, and you get your separate actions.
If I understand your problem right you have a lot of switch code in action.
I think you can use Factory pattern. You can create factory that will accept switch parameter as parameter and will return ActionResult instance.

Where to put ParseUrl() or similar function that works against a datastore, in ASP.NET MVC?

If you were to code a function/method that would, for entered string or slug (for instance in Create or Edit view), go into datastore and check whether that string or slug exists and in this case create a link to it, where would you put it?
For instance, we have a "Link" textbox on our Create or Edit form. I have a jQuery autocomplete wired to it, which retrieves existing Page slugs. If a user decides to select one of them, we would create a link that points to the content within our site, based on the Page controller, like this:
~/Page/Display/some-slug
or just
~/Page/some-slug
If, however, user decides not to select anything and inputs for instance www.google.com, we catch it in our ParseUrl(), format it with http://... etc. and store it like that.
The code for the function is no problem and I have it working currently in a Model Binder. However, due to strange, confusing and opposing practices with DI in Model Binders I would like to move it somewhere else. Another reason would be to remove dataccess code from Model Binders.
The question is - where to move such funcionality? If possible, I would like to avoid repeating ParseUrl() calls across various controller actions.
1) Implement it so it makes sense to you and your team.
-or-
2) Leave it where it is because its already working.
Is moving it going to make your app better, will your customers be happier, deadlines met faster?
There is no magic Asp.net MVC thunder-god that descends from the heavens to smite you if you dare use the wrong extensibility point. Nobody is going to call you an idiot. People may disagree, but that happens. Its ok to "go for it" and get things done before being architecturally pure.
"However, due to strange, confusing and opposing practices with DI in Model Binders"
What does that even mean?

How much logic do you put in views?

I am currently unconfident, if I can put a "if/else"-construct into my view?
How much logic do you put in your views?
My dilemma:
I am rendering a navigation. So, I have to differ between the current/active menu item and the rest. The current menu item gets a special css class. I don't know how to handle this in a better way than using if-else.
If you are doing MVC (hopefully you do), than the question is "Do I put the logic in the view or the controller?". I use a simple rule to find out the answer of that:
What if my view was not HTML, but an XML document?
If I will need this logic in both circumstances - its place is in the controller. If not - it's in the view.
In good MVC design you should be able to swap the views without touching the controller.
As much as is necessary to display the information. Just remember that the view is just a window into the internal state of the program. If you stripped the view layer completely away, the program should still be able to operate as usual, just without being able to see what it's doing.
edit: re your navigation, that seems like an okay use of an if statement. The information about which is active is still coming from the model, you're simply using the if statement to decide how to display it. You might consider a little bit about how you're rendering your navigation: is the information about which navigation items available, and which to render living in your view or your model?
One way you might choose to approach the situation is to have the model give you a list of navigation items, along with which one is active, and program the view to know how to generate appropriate HTML from that. That code might contain precisely one if statement total. (instead of one for each nav item).
I wouldn't worry about putting an if statement in a view. In fact, I think there's a bit too much hand-wringing (in general) about responsibilities in these kinds of situations.
If you make your views too dumb then your model can become too view-sentric (tightly coupled).
IMHO a view can do what it likes but the guiding principle should be: where does it get its information from? If the answer is "the model" then use as much logic as you like.
An "if/else" construct is fine if the view is alternating modes, e.g. formatting a U.S. address vs. a foreign address in an order screen.
However, any logic that you place into a view should not alter the model.
Add this helper to your application_helpers.rb It will surround your links with <li> and <li class="active"> if the link is the current page.
Use it in place of a link_to.
link_to 'home', root_url, optional_condition_argument_goes_here
def active_link_to(text, url, condition = nil)
if condition.nil? and String === url
condition = url == request.path
end
content_tag :li, link_to(text, url), :class => (condition && 'active')
end
(Courtesy of Mislav)
I might put if-else in a view. In most cases not. The real question in my mind is whether the logic could go anywhere else without being messier.
I tend to avoid putting control-flow logic in my views (ASP.NET MVC) except under circumstances where I may want a portion of the interface visible/not visible based on the presence or absence of data. In this case, it is view logic -- I'm determining the layout of the page, the elements of the page that are available, etc. I think that this is perfectly acceptable and preferable to having the controller determine this or multiplying views to account for minor variants. The controller needs to give the view enough information for it to be able to render the view and its variants as needed.
What I wouldn't put into the view is business logic that determines how to calculate something or whether to perform some action (except, perhaps, for role-based decisions -- these seem to crop up just about everywhere). Other than client-side validation, my business logic resides in the controller/model.
An example of where I might use if/then logic in a view is a view which displays events. In my app, events can have subevents, but subevents can't have further subevents: a two level hierarchy. On my display page, I have tabs for Details, Groups, Participants, and Subevents. These are the same for both events and subevents, with the exception of the Subevent tab. It shouldn't exist for a subevent. Rather than repeat myself by having two different views that are virtually identical except for that one tab, I've added a tiny amount of logic to the view to not render the Subevent tab if an event has none.
By the same token, I wouldn't go so far as to have a single "view" that uses logic to determine whether to show an overview or details or editing pane, etc. based on the value of some view data item. This seems an abuse of the single responsibility principle as applied to views. Each view should have a single-purpose, IMO.
Logic that is in the view should not be required to fully describe the current state of the model.
Said another way, logic in the view is acceptable if that logic is used to format or alter the visualization of the information. Logic in the view might also have a use in vetting data that is entered before taking the expense of transmitting that data to the controller (in a client/server or web application).
For instance, the view might include logic to split a list of items into multiple columns when the list is longer than N items. That split could be done in several different ways according to the exact nature of the view (e.g. http, mobile device, pdf, voice reader, Morris Code, etc, etc, ad nasium). The full view information might need to be paginated - and that can only be done in the view. Formatting logic should not ever be included in the controller or the model.
As a corner case, the view might include logic to check that a password entered for a new user meets the current security requirements (e.g. double entry of password matches; at least N characters long; does not include spaces or the "*" character; includes at least three of the following: lower case letters, upper case letters, numbers, symbols; is different than the last N passwords, no based on a dictionary word, etc, etc). Depending on the nature of the logic, vetting a password could be thought of as "formatting" or as "business logic". It might be that the check happens in two passes - one set of checks for formatting in the view, and another set of checks in the controller with info from the model (the last N passwords).

Resources