I am currently refactoring some of my old code that is pretty terrible. I will have a class that creates a Treeview, populates the node, etc and is displayed on a Winform.
Each node on the Treeview represents some data and when the user clicks on that then a datagridview is also displayed on the Winform. The datagridview will be generated within a new class also.
My idea on this is, when the Winform Loads, create and display the Treeview and use an event to monitor for node clicks. When the Winform handles such an event, then it creates the datagrid object and diplays that.
IS this the best way to architect this?
Thanks.
Yes, what you describe is a standard way to do things in WinForms.
You don't need to create the DataGridView every time though - just place it on the Form and in the event handler load the data from somewhere and change the contents of the DataGridView by assigning to DataGridView.DataSource.
In the form designer, define columns for DataGridView and set their DataPropertyName to the names of the corresponding properties of the data objects in the collection.
Note: the data assigned to the DataGridView.DataSource can be a collection of objects or also a DataTable if you are using ADO.NET to read the objects from a database.
Just use the TreeView.AfterSelect event. It fires anytime the user selects another node, either by keyboard or mouse. Be sure to dispose the old DGV if you replace it completely.
Related
through C # I am creating a program that manages ambulances, I am trying to create a list with the events and active missions, this data must be taken from a mysql database, I have tried to see many "tutorials", but none explained what I needed, how do you think I can do something like this?
image here
in addition to displaying the data, if I click twice it should open the event or mission to me depending on where I click, (the icons are also buttons that should only be visible if there is a data)
just a tip! I'm not asking you to write the code for me!!!
EDIT:
I managed to get the data from mysql, that you know is it possible to place the data in specific columns?
Program
Code
It is difficult to guide you through such unspecific question, but I'll try some hints.
You said you have data from MySQL
Fill a DataTable (another way is to use BindingSource)
Assign DataTable as a DataSource of your DataGridView grid.
You can edit columns in the DataGridView using UI in VS, or you can do it programatically. First is easier, just note that if you at any stage provide Nothing as a data source, you'll loose column headers.
For event fired on DataGridViewRow, click on the grid in Designer, click on events in the Properties pane, find DatagridviewRow_DoubleClick and double click the line, to create associated method
FIll in the code into the even method. Use DataGridView.SelectedRows(0) to get selected row and it's index. If you want to "open it" create a modal dialog or what you want for displaying the content.
When I first started working on this project I had never worked with anything .NET, much less C# or WinForms, so if any of what I've done is bringing you to the point of tears, please let me know what the best practice would be for this set up.
I am working on a scheduling system. I have the events in a database and I get those from a web service onto a master list for the application to use. This Event class contains a list of activities (List):
[Global class]
public List<Event> Events = Service.GetEvents();
I have a DataGridView that displays the events and a second Datagridview that displayed the event activities. I also have a "Save" button that would only be enabled if an event had changed in any way. Here's how I have that set up:
[EventsView form]
BindingSource eventsBindingSource = new BindingSource();
BindingSource activitiesBindingSource = new BindingSource();
List<Event> events = new List<Event>(Global.Events.ToList());
eventsBindingSource.DataSource = events;
activitiesBindingSource.DataSource = ((Event)eventsBindingSource.Current).Legs //updated when clicked on new row.
eventsDataGridView.DataSource = eventsBindingSource;
activitiesDataGridView.DataSource = activitiesBindingSource;
I have it set so that when the CellValueChanged on the avtivitiesDataGridView, it would check the activitiesBindingSource.Current, look-up the activities for that event in the original Global.Events list and if it differs it would enable the "Save" button.
However, when I check to see if the values differ, lo and behold, the Global.Events list has already been updated, even though the BindingSource is set to the events list, which is a copy of that list.
Does BindingSource have it so that if the list is a copy, it would update the original as well?
The reason why I don't want it to update it automatically and save it is so that I can update the web service when the user clicks save only.
I've also tried the following:
Having the (copy) events list be a BindingList
Copying the events from the global list one by one
bypass the BindingSource and setting the DGV's datasource to the List
This used to work when I had Global.Events be a different class that I used for the sole purpose of transfer between the web service and the application (because the Entity Framework would have collections that could not pass through), but since I've changed that list to have the already-converted Event objects it had been able to update it that far automatically.
Is there a UpdateMode similar to the one in DataBindings where I could set it not to update unless I tell it to? Or am I just going at this all wrong?
Thank you for your help, let me know if you need more details about this.
When the data is bound to the DataGridView, the DGV doesn't care much what the Events are stored in. Whether you're using the original (Global) list of Events or even manually copying the list, the fact of the matter is that the Event objects are the same throughout and therefore, when the user makes changes (through the DGV), the original Events change.
One way of implementing this "Saving" model would be to:
Clone the original Events from the global list (consider implementing ICloneable).
Setup the DataSource of the DGV to point to these cloned Events.
When a "Save" is performed, match up the original Events to the cloned Events (possibly through a unique identifier) and copy the changed information to the original Events.
I'm pretty new to c# and Winforms and I'm wondering what is the best approach to the following screen design.
I have a window that contain a Datagrid wich would be read-only. Beneath the grid, I have the detail of the records in differents fields (textbox, combobox, checkbox).
What I want is that when the user click on an item in the datagrid, the data will be shown in the detail fields.
That part is pretty easy, but I want to be able to update the fields automatically, wich means, I would prefer to not have to press a Save button.
Let's say that I click an item in the datagrid, change some value in the detail fields and the I click on another item in the datagrid, then I also want to perform some validation and calculation before the record get updated.
What I was thinking at first was to get the button for "new", "edit", "save" action and lock and unlock the fields accordingly and keep a flag to know if i need to insert or update the data, but then I realized that I would prefer to not have thoses button and have the save performed automatically.
Is there any sample somewhere that does what I want?
Also, would you guys using the built-in databinding functunality or just use a dataset object in code?
Pretty common scenario.
On selected row change of grid you know which datarow you shoul bind to the other controls. when same event happens again you validate and save or cancel in case of errors.
You can make use of DataGridView.CellEndEdit Event to get the new value and DataGridView.CellBeginEdit event to get the old value and update your data if there is any change
I have a windows form application that has two main panels: The one on the left is a narrow strip which has a series of radio buttons. The panel on the right houses a Tabcontrol, which has multiple Tabpages added to it which the user can select among along the top. Each of these tabpages themselves has about 7 DataGridViews added to it. Each DataGridView has about 5-6 columns of text, with a variable number of rows (10-500). The data added to it was done directly to the DGV itself, ie using the DGV.Rows.Add() method, passing an object array, not via a datasource.
When a user selects a different tab page, the datagridview that gets shown is dependent on the radiobutton that is selected on the left. I accomplish this by handling the SelectedIndexChange event of the tabcontrol and each of the radiobutton's CheckedChange event.
Within the SelectedIndexChange event of the tabcontrol, I programmatically checked the currently selected radioButton. Then within the radiobutton's CheckedChange event, I iterate through all of the DataGridViews on the TabControl's selectedTab and hide all those that don't match the one corresponding to the selected radiobutton.
My issue is everytime the user starts changing among a lot of tabs, or tries to view a DGV that has many rows, the program would throw the following error:
System.ComponentModel.Win32Exxception: Error creating window handle.
Does anyone know what would cause the above error? My initial suspicion was that when I change to a different tabpage, the DGV on the original tabpage i was on was still in memory, but when I try calling .Dispose() on it, the DGV just disappears. It may be I am missing something fundamental here.
The problem is that you are probably trying to show a disposed DataGridView.
Do not dispose any Control in your form unless you are previously removing it from the appropiate Container.Controls collection (because you do not need it anymore and/or you plan adding a new one in its place). Otherwise dispose any controls when closing and disposing the Form that contains them if necessary.
In order to show the proper DataGridView depending on selected tab and user options use the Visible property or dynamically add and remove the needed controls to the container's Controls collection (in this case TabPage.Controls.
If its not that then maybe you have a "control leak" (probably event handler holding the object) and you are exceeding the windows handle limit for any given application (10.000 I think it is).
I have this GridView that have it's DataSource as a list of previously selected products.
For every item on it, I need to Eval it's ID and load a specifc form that the user must fill, then after that i've got to update the GridView.
I have made those specific forms as User Controls, is this the best approach for this scenario?
If yes, how can I dynamically load them, in a way that I can make queries/postbacks then update back my gridview?
What you want to develop is called Master/Detail view.
It is described for example in http://www.asp.net/data-access/tutorials/master-detail-using-a-selectable-master-gridview-with-a-details-detailview-cs .
The only difference that as Detail you need use FormView, where on some initialization event (like DataBound http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.basedataboundcontrol.databound.aspx )you need to dynamically create you control and set its parent to current template of FormView