I have a form with a grid and I want to pass info from the first form to second based on which row is selected when the user clicks the edit button.
what is the best way? and how should I decide how the form should be blank if the the user wants to add a new or fill the second(edit) form with the values from the selected row of the first forms datagrid?
The row values are all properties of the same object.
I can delete and add a new object, its editing an exsisting one that I am having a hard time with, and how should I load the second form?
I am currently creating and instance then instance.Show();
This is working the open a blank form, but I want to loadd it with the object based on the selected row when the user wants to edit an exsisting record.
Let's say your form1 is the form with data grid (grdMyData) that's displaying rows of MyClass class instances, and form2 is the form for editing the data of the given row.
When user clicks Edit, you could use this:
private void btnEdit_Click(sender e, EventArgs arg)
{
if (grdMyData.SelectedRows.Count == 0)
return; //nothing to do
MyClass selectedRow = (MyClass)grdMyData.SelectedRows[0].DataBoundItem;
Form2 frm2 = new Form2(selectedRow);
if (frm2.ShowDialog() == DialogResult.OK)
{
//do something if needed
}
}
This code is assuming you have the proper Form2 constructor which takes the type of object it works with. With this when you are working in Form2 the data will automatically affect the Form1 display because they're working with the instance of the same object.
I would suggest exposing an event in one form that the other form can consume.
Here is the offical tutorial
http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspx
Basically it would be something like this
// Source form
public event YourEventHandlerType EventName;
// Wherever the event occurs
EventName.Invoke(...);
// Destination form
this.referenceToSourceForm.EventName += MyEventHandler(...);
So, you will need some reference to the source form in the destination form, or you will need to setup the event handling outside of the two forms otherwise.
Related
Simple problem but can't find a solution: I have a Thymeleaf form used to add a new object, say of a Book class. It works perfectly well and I only need that particular form for adding new objects, not editing the existing ones. The question is: how can I put several objects of the Book class in the same single form? So, purely for convenience, instead of filling form for a single book and clicking Send you can fill form for several books at once and only then click Send, have them all inserted into the database (in whatever order) and also have the option to fill the form partially (e.g. the form has room for 5 books but it will also accept 1, 2, 3 or 4 and you can leave the rest blank).
Edit: I've tried passing a list of object to the Thymeleaf template with the form bound to the whole list and iteration inside, but Thymeleaf throws BingingResultError upon rendering it.
You need to use a wrapper object to realize what you want.
Something like:
public class BooksCreationDto {
private List<Book> books;
// default and parameterized constructor
public void addBook(Book book) {
this.books.add(book);
}
// getter and setter
}
Then you need to pass this object as a model attribute in your controller:
BooksCreationDto booksForm = new BooksCreationDto();
model.addAttribute("form", booksForm);
bind fields using index property
th:field="*{books[__${itemStat.index}__].title}"
and get back the result with
#ModelAttribute BooksCreationDto form
in your controller.
For a complete and detailled explaination visit: https://www.baeldung.com/thymeleaf-list
I have a form that I open to have the user select data from. Then I want to send that data back to the form that was spawned that data. Here is my code from the parent form:
Private Sub bttn_AW_SelectUnits_Click(sender As Object, e As EventArgs) Handles bttn_AW_SelectUnits.Click
'TODO: Capture output from next menu
Dim changeUnits As New AuditWizardUnits
changeUnits.ShowDialog()
End Sub
I could have it spawn a new form, but I have multiple forms that I want to collect data from, so I don't want to lose the data that has been collected already. I tried to google this, but all I can find is how to send data, not receive it. I also couldn't find how to do this beyond a binary "OK" or "cancel."
Does know how to do this?
The DialogResult portion simply allows you to determine if the User selected "OK" (or your equivalent of "OK"), or simply cancelled the dialog by clicking the "X" in the top right (in which case there might not be any valid "selections" in the dialog to retrieve).
If the User clicked "OK", then you can retrieve any desired values from the form reference that you already have. Conceptually, we are "pulling" from the main form, not "sending" from the child form. This is easier because the main form already has a reference to the child form (you used that reference to display the dialog!).
To do the opposite, and "send" from the dialog to the main, you'd have to pass a reference to the main form into the dialog form. There are cases where you'd want to do this, such as if you needed something to change in main, in real-time and possibly multiple times, before the dialog is closed by the user. Sometimes you need to only "pull", sometimes you need to "send", and sometimes you might need to do both. You'll have to decide which approach is best for your situation.
Assuming you only need to pull after the dialog is dismissed by the user, check the returned DialogResult, then use that form reference to retrieve the values:
Private Sub bttn_AW_SelectUnits_Click(sender As Object, e As EventArgs) Handles bttn_AW_SelectUnits.Click
'TODO: Capture output from next menu
Dim changeUnits As New AuditWizardUnits
If changeUnits.ShowDialog() = DialogResult.Ok Then
' Access something directly from a Control:
Dim value As String = changeUnits.TextBox1.Text
' ...or use a property that YOU created in changeUnits:
Dim values As List(Of String) = changeUnits.SelectedValues
End If
End Sub
In the dialog, you return "OK" when the user clicks on your OK/Save/Continue type button:
Private Sub btnOK_Click(...) Handles btnOK.Click
Me.DialogResult = DialogResult.Ok
End Sub
For the List aspect, you'd have to make that List accessible from outside the class so it can be retrieved like in my snippet above:
Public Class AuditWizardUnits
Public SelectedValues As New List(Of String)
End Class
You'd either populate that list before setting DialogResult, or populate it as the user interacts with the dialog.
I've created a form in which a user can double click on a list box entry to open another form for info. When the user closes the new form I want the existing data on the original form to remain. In my current code, however, the original data is not retained if the user clicks "X" to close the new form.
Code:
Private Sub lstServiceHistory_DblClick (ByVal Cancel As MSForms.ReturnBoolean)
frmJobDetails.Show
End Sub
How can I get the data to remain on the original form?
I solved the problem by adding a boolean check in the form_Activate event to see if the form had already been initialised.
I'm working with some old VB6 code and have a scenario I'm trying to correct. I have a form that allows you to enter a person ID (use renters this in a textbox at the top) and click "show" it lists the appointment in the textbox on the same form. There is also a button that loads a new form that allows the user to edit the displayed data and save the change.
E.g. Change persons age from 65 to 64. I make this change, and save it. The save is successful and I unload the form to return to Form1. However, I must click "show" again to refresh the displayed data in the textbox to ensure the change is visible. I cannot figure out how to refresh this form, so the user doesn't have to click "show" to repopulate the textbox with the new value. Can anyone assist? I can't just create a new instance of Form1, because if I did that the person ID field would be blank.
Thanks!
Short version: How do I refresh a form to get latest data while still obtaining the relevant person ID.
There's not enough information here to answer your question. The general pattern you'd use in this situation is as follows:
SearchForm launches ViewForm.
ViewForm launches EditForm. When ViewForm constructs its instance of EditForm, it passes Me to EditForm (perhaps by setting EditForm.Parent).
When EditForm's Save button click event fires, it calls Parent.ReloadData (where Parent is the ViewForm that launched the EditForm).
Here is the approach that should work. In the editor have a public property that returns whether the form was cancelled or not. (.Cancelled). You'll have an object that carries attributes of the person that you are trying to change the age of. Then it's pretty simple. Code in the main form:
dim oPerson as clsPerson
dim oFrm as frmAgeEditor
set oPerson = GetCurrentPerson()
set oFrm = new frmAgeEditor
with oFrm
set .Person = oPerson
.Show vbModal
if not .Cancelled then
' Update Main form with the contents of oPerson
end if
end with
You can just call in "Show" function right after updating.
Call Me.frmParent.Refresh
I used this to refresh the screen without losing data.
I had to dig through a lot of old code to figure it out. This section had been written a long time ago, and worked well.
Public Sub Refresh()
Call cmdDetails_Click
If tvwScreeningSchedule.Nodes.Count > 0 Then
tvwScreeningSchedule.SelectedItem = tvwScreeningSchedule.Nodes(1)
Call tvwScreeningSchedule_Click
End If
End Sub
It's quite a specific function, and "cmdDetails_Click" contains alot of custom validation, but it's not too dis-similar to AngryHackers answer.
I have an existing ASP.NET MVC 2 application that I've been asked to extend. I am adding a new feature to the site where I generate an employee assessment form based on a dynamic list of questions retrieved from our HR system. I have everything working with the exception of validation and posting the responses back to the site. Here's some details:
I retrieve a list of "Questions" from our back-end system via a web service call.
Each "Question" contains the text to display as well as the following settings:
The question Type (corresponds to textbox, textarea, radio button list or checkbox list)
If comments are allowed
If an answer is required
When applicable, the list of possible responses
To generate the form, I use a for-each loop over the list of Questions. I use the value of the QuestionType property to determine which partial view to render (one for each of the types). For example, if QuestionType == SingleChoice, that partial renders the choices as a radio button list. If comments are allowed for the question, I also render an additional textarea field to hold the user's comments.
As I said, rendering the form is working fine but now I need to:
A. Enforce when an answer is required. I'm using DataAnnotations for validation everywhere else in the solution but since I'm not working against a static model, I don't see how I can do that.
B. Post the results back to the site. For each question, there can be text entered into a textbox or textarea, a selected value for a radio button list or multiple selected values for a checkbox list. Plus, each question could also have additional text sent back in the form of a comment.
All of the examples that I've seen working with dynamic "lists" are only concerned with posting a single value for each field and it is always the same type (e.g. a list of textboxes). With the variations I have to support, plus the need to send back the entered/selected value(s) and a comment for each question, I'm stumped.
Any guidance is appreciated.
I've just finished completing exactly the same task.
I chose to write a custom model binder for my dynamic form object. The model binder pulled out a bunch of prefixed form keys for hidden fields which contained some delimited meta data about the question (i.e IsRequired, QuestionType, QuestionId etc etc)
I'm using MVC3 but I think this should all work in MVC2.
I created a ModelBinder like:
public class DynamicFormModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// Create the object to be bound to (I had a kind of form object
// with a simple list of answer objects
DynamicForm form = new DynamicForm(new List<Answer>());
HttpRequestBase request = controllerContext.HttpContext.Request;
var keys = request.Form.AllKeys.Where(k => k.StartsWith("MyFormsKeyPrefix_Meta_"));
foreach (var key in keys)
{
// Loop over each question's meta data. Metadata will always be present
// even if the user hasn't selected an answer as it's a hidden field
// TODO: Split the meta data and pull out IsRequired, QuestionType etc
// TODO: Get all the posted form values for the question (these values
// will come from textboxes, dropdowns, checkboxes etc)
// Use a prefix like: MyFormsKeyPrefix_Answer_{QuestionId}
// textboxes & dropdowns will only ever have one value
// but checkboxes could have multiple
// TODO: If it's a mandatory question then ensure there is at least
// one posted value that is not an empty string
// If there is a validation error then add it to the model state
bindingContext.ModelState.AddModelError(key, "Field is required");
foreach(var answerHtmlName in answerHtmlNames)
{
// TODO: Loop over each posted answer and create some kind of nice
// Answer object which holds the QuestionId, AnswerId, AnswerOptionId
// and Value etc.
// Add the answer to the forms answers list
form.Answers.Add(answer);
}
}
return form;
}
}
I register the ModelBinder in Global.asax using the following:
ModelBinders.Binders.Add(typeof(DynamicForm), new DynamicFormModelBinder());
So, the action method that recieves the form post looks something like:
public ActionResult ProcessForm(DynamicForm form) {
if(ModelState.IsValid)
{
DynamicFormService.Process(form);
return RedirectToAction("TheHttpGetAction");
}
return TheHttpGetAction();
}